1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-18 18:42:46 +02:00

[libFuzzer] add -minimize_crash flag (to minimize crashers). also add two tests that I failed to commit last time

llvm-svn: 280332
This commit is contained in:
Kostya Serebryany 2016-09-01 01:22:27 +00:00
parent 7b2700391a
commit d575db2f6f
5 changed files with 116 additions and 9 deletions

View File

@ -215,16 +215,27 @@ static void WorkerThread(const std::string &Cmd, std::atomic<int> *Counter,
}
}
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(), 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;
for (auto &S : Args) {
if (FlagValue(S.c_str(), "jobs") || FlagValue(S.c_str(), "workers"))
continue;
Cmd += S + " ";
}
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, UserCallback Callback) {
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, UserCallback Callback) {
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, UserCallback Callback) {
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, UserCallback Callback) {
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, UserCallback Callback) {
exit(0);
}
if (Flags.merge) {
if (Options.MaxLen == 0)
F.SetMaxLen(kMaxSaneLen);

View File

@ -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")

View File

@ -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-*

View File

@ -0,0 +1,3 @@
CHECK: AddressSanitizer: FPE
RUN: not LLVMFuzzer-DivTest -seed=1 -use_value_profile=1 -runs=10000000 2>&1 | FileCheck %s

View File

@ -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