[llvm] r280332 - [libFuzzer] add -minimize_crash flag (to minimize crashers). also add two tests that I failed to commit last time
Kostya Serebryany via llvm-commits
llvm-commits at lists.llvm.org
Wed Aug 31 18:22:28 PDT 2016
Author: kcc
Date: Wed Aug 31 20:22:27 2016
New Revision: 280332
URL: http://llvm.org/viewvc/llvm-project?rev=280332&view=rev
Log:
[libFuzzer] add -minimize_crash flag (to minimize crashers). also add two tests that I failed to commit last time
Added:
llvm/trunk/lib/Fuzzer/test/minimize_crash.test
llvm/trunk/lib/Fuzzer/test/value-profile-div.test
llvm/trunk/lib/Fuzzer/test/value-profile-load.test
Modified:
llvm/trunk/lib/Fuzzer/FuzzerDriver.cpp
llvm/trunk/lib/Fuzzer/FuzzerFlags.def
Modified: llvm/trunk/lib/Fuzzer/FuzzerDriver.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/FuzzerDriver.cpp?rev=280332&r1=280331&r2=280332&view=diff
==============================================================================
--- llvm/trunk/lib/Fuzzer/FuzzerDriver.cpp (original)
+++ llvm/trunk/lib/Fuzzer/FuzzerDriver.cpp Wed Aug 31 20:22:27 2016
@@ -215,16 +215,27 @@ static void WorkerThread(const std::stri
}
}
-static int RunInMultipleProcesses(const std::vector<std::string> &Args,
- int NumWorkers, int NumJobs) {
- std::atomic<int> Counter(0);
- std::atomic<bool> HasErrors(false);
+static std::string CloneArgsWithoutX(const std::vector<std::string> &Args,
+ const char *X1, const char *X2) {
std::string Cmd;
for (auto &S : Args) {
- if (FlagValue(S.c_str(), "jobs") || FlagValue(S.c_str(), "workers"))
+ if (FlagValue(S.c_str(), X1) || FlagValue(S.c_str(), X2))
continue;
Cmd += S + " ";
}
+ return Cmd;
+}
+
+static std::string CloneArgsWithoutX(const std::vector<std::string> &Args,
+ const char *X) {
+ return CloneArgsWithoutX(Args, X, X);
+}
+
+static int RunInMultipleProcesses(const std::vector<std::string> &Args,
+ int NumWorkers, int NumJobs) {
+ std::atomic<int> Counter(0);
+ std::atomic<bool> HasErrors(false);
+ std::string Cmd = CloneArgsWithoutX(Args, "jobs", "workers");
std::vector<std::thread> V;
std::thread Pulse(PulseThread);
Pulse.detach();
@@ -266,6 +277,80 @@ static bool AllInputsAreFiles() {
return true;
}
+int MinimizeCrashInput(const std::vector<std::string> &Args) {
+ if (Inputs->size() != 1) {
+ Printf("ERROR: -minimize_crash should be given one input file\n");
+ exit(1);
+ }
+ if (Flags.runs <= 0 && Flags.max_total_time == 0) {
+ Printf("ERROR: you need to use -runs=N or "
+ "-max_total_time=N with -minimize_crash=1\n" );
+ exit(1);
+ }
+ std::string InputFilePath = Inputs->at(0);
+ std::string BaseCmd = CloneArgsWithoutX(Args, "minimize_crash");
+ auto InputPos = BaseCmd.find(" " + InputFilePath + " ");
+ assert(InputPos != std::string::npos);
+ BaseCmd.erase(InputPos, InputFilePath.size() + 1);
+ // BaseCmd += " > /dev/null 2>&1 ";
+
+ std::string CurrentFilePath = InputFilePath;
+ while (true) {
+ Unit U = FileToVector(CurrentFilePath);
+ if (U.size() < 2) {
+ Printf("CRASH_MIN: '%s' is small enough\n", CurrentFilePath.c_str());
+ return 0;
+ }
+ Printf("CRASH_MIN: minimizing crash input: '%s' (%zd bytes)\n",
+ CurrentFilePath.c_str(), U.size());
+
+ auto Cmd = BaseCmd + " " + CurrentFilePath;
+
+ Printf("CRASH_MIN: executing: %s\n", Cmd.c_str());
+ int ExitCode = ExecuteCommand(Cmd);
+ if (ExitCode == 0) {
+ Printf("ERROR: the input %s did not crash\n", CurrentFilePath.c_str());
+ exit(1);
+ }
+ Printf("CRASH_MIN: '%s' (%zd bytes) caused a crash. Will try to minimize "
+ "it further\n",
+ CurrentFilePath.c_str(), U.size());
+
+ std::string ArtifactPath = "minimized-from-" + Hash(U);
+ Cmd += " -minimize_crash_internal_step=1 -exact_artifact_path=" +
+ ArtifactPath;
+ Printf("CRASH_MIN: executing: %s\n", Cmd.c_str());
+ ExitCode = ExecuteCommand(Cmd);
+ if (ExitCode == 0) {
+ Printf("CRASH_MIN: failed to minimize beyond %s (%d bytes), exiting\n",
+ CurrentFilePath.c_str(), U.size());
+ return 0;
+ }
+ CurrentFilePath = ArtifactPath;
+ Printf("\n\n\n\n\n\n*********************************\n");
+ }
+ return 0;
+}
+
+int MinimizeCrashInputInternalStep(Fuzzer *F) {
+ assert(Inputs->size() == 1);
+ std::string InputFilePath = Inputs->at(0);
+ Unit U = FileToVector(InputFilePath);
+ assert(U.size() > 2);
+ Printf("INFO: Starting MinimizeCrashInputInternalStep: %zd\n", U.size());
+ Unit X(U.size() - 1);
+ for (size_t I = 0; I < U.size(); I++) {
+ std::copy(U.begin(), U.begin() + I, X.begin());
+ std::copy(U.begin() + I + 1, U.end(), X.begin() + I);
+ F->AddToCorpus(X);
+ }
+ F->SetMaxLen(U.size() - 1);
+ F->Loop();
+ Printf("INFO: Done MinimizeCrashInputInternalStep, no crashes found\n");
+ exit(0);
+ return 0;
+}
+
int FuzzerDriver(int *argc, char ***argv, UserCallback Callback) {
using namespace fuzzer;
assert(argc && argv && "Argument pointers cannot be nullptr");
@@ -281,6 +366,9 @@ int FuzzerDriver(int *argc, char ***argv
return 0;
}
+ if (Flags.minimize_crash)
+ return MinimizeCrashInput(Args);
+
if (Flags.close_fd_mask & 2)
DupAndCloseStderr();
if (Flags.close_fd_mask & 1)
@@ -319,7 +407,7 @@ int FuzzerDriver(int *argc, char ***argv
Options.RssLimitMb = Flags.rss_limit_mb;
if (Flags.runs >= 0)
Options.MaxNumberOfRuns = Flags.runs;
- if (!Inputs->empty())
+ if (!Inputs->empty() && !Flags.minimize_crash_internal_step)
Options.OutputCorpus = (*Inputs)[0];
Options.ReportSlowUnits = Flags.report_slow_units;
if (Flags.artifact_prefix)
@@ -333,7 +421,8 @@ int FuzzerDriver(int *argc, char ***argv
if (Flags.verbosity > 0 && !Dictionary.empty())
Printf("Dictionary: %zd entries\n", Dictionary.size());
bool DoPlainRun = AllInputsAreFiles();
- Options.SaveArtifacts = !DoPlainRun;
+ Options.SaveArtifacts =
+ !DoPlainRun || Flags.minimize_crash_internal_step;
Options.PrintNewCovPcs = Flags.print_pcs;
Options.PrintFinalStats = Flags.print_final_stats;
Options.TruncateUnits = Flags.truncate_units;
@@ -371,6 +460,9 @@ int FuzzerDriver(int *argc, char ***argv
if (Flags.handle_int) SetSigIntHandler();
if (Flags.handle_term) SetSigTermHandler();
+ if (Flags.minimize_crash_internal_step)
+ return MinimizeCrashInputInternalStep(&F);
+
if (DoPlainRun) {
Options.SaveArtifacts = false;
int Runs = std::max(1, Flags.runs);
@@ -393,7 +485,6 @@ int FuzzerDriver(int *argc, char ***argv
exit(0);
}
-
if (Flags.merge) {
if (Options.MaxLen == 0)
F.SetMaxLen(kMaxSaneLen);
Modified: llvm/trunk/lib/Fuzzer/FuzzerFlags.def
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/FuzzerFlags.def?rev=280332&r1=280331&r2=280332&view=diff
==============================================================================
--- llvm/trunk/lib/Fuzzer/FuzzerFlags.def (original)
+++ llvm/trunk/lib/Fuzzer/FuzzerFlags.def Wed Aug 31 20:22:27 2016
@@ -37,6 +37,10 @@ FUZZER_FLAG_INT(help, 0, "Print help.")
FUZZER_FLAG_INT(merge, 0, "If 1, the 2-nd, 3-rd, etc corpora will be "
"merged into the 1-st corpus. Only interesting units will be taken. "
"This flag can be used to minimize a corpus.")
+FUZZER_FLAG_INT(minimize_crash, 0, "If 1, minimizes the provided"
+ " crash input. Use with -runs=N or -max_total_time=N to limit "
+ "the number attempts")
+FUZZER_FLAG_INT(minimize_crash_internal_step, 0, "internal flag")
FUZZER_FLAG_INT(use_counters, 1, "Use coverage counters")
FUZZER_FLAG_INT(use_indir_calls, 1, "Use indirect caller-callee counters")
FUZZER_FLAG_INT(use_traces, 0, "Experimental: use instruction traces")
Added: llvm/trunk/lib/Fuzzer/test/minimize_crash.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/test/minimize_crash.test?rev=280332&view=auto
==============================================================================
--- llvm/trunk/lib/Fuzzer/test/minimize_crash.test (added)
+++ llvm/trunk/lib/Fuzzer/test/minimize_crash.test Wed Aug 31 20:22:27 2016
@@ -0,0 +1,6 @@
+CHECK: CRASH_MIN: failed to minimize beyond minimized-from-{{.*}} (3 bytes), exiting
+RUN: echo 'Hi!rv349f34t3gg' > not_minimal_crash
+RUN: LLVMFuzzer-NullDerefTest -minimize_crash=1 not_minimal_crash -max_total_time=2 2>&1 | FileCheck %s
+RUN: rm not_minimal_crash minimized-from-*
+
+
Added: llvm/trunk/lib/Fuzzer/test/value-profile-div.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/test/value-profile-div.test?rev=280332&view=auto
==============================================================================
--- llvm/trunk/lib/Fuzzer/test/value-profile-div.test (added)
+++ llvm/trunk/lib/Fuzzer/test/value-profile-div.test Wed Aug 31 20:22:27 2016
@@ -0,0 +1,3 @@
+CHECK: AddressSanitizer: FPE
+RUN: not LLVMFuzzer-DivTest -seed=1 -use_value_profile=1 -runs=10000000 2>&1 | FileCheck %s
+
Added: llvm/trunk/lib/Fuzzer/test/value-profile-load.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/test/value-profile-load.test?rev=280332&view=auto
==============================================================================
--- llvm/trunk/lib/Fuzzer/test/value-profile-load.test (added)
+++ llvm/trunk/lib/Fuzzer/test/value-profile-load.test Wed Aug 31 20:22:27 2016
@@ -0,0 +1,3 @@
+CHECK: AddressSanitizer: global-buffer-overflow
+RUN: not LLVMFuzzer-LoadTest -seed=1 -use_value_profile=1 -runs=10000000 2>&1 | FileCheck %s
+
More information about the llvm-commits
mailing list