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:
parent
7b2700391a
commit
d575db2f6f
@ -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);
|
||||
|
@ -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")
|
||||
|
6
lib/Fuzzer/test/minimize_crash.test
Normal file
6
lib/Fuzzer/test/minimize_crash.test
Normal 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-*
|
||||
|
||||
|
3
lib/Fuzzer/test/value-profile-div.test
Normal file
3
lib/Fuzzer/test/value-profile-div.test
Normal file
@ -0,0 +1,3 @@
|
||||
CHECK: AddressSanitizer: FPE
|
||||
RUN: not LLVMFuzzer-DivTest -seed=1 -use_value_profile=1 -runs=10000000 2>&1 | FileCheck %s
|
||||
|
3
lib/Fuzzer/test/value-profile-load.test
Normal file
3
lib/Fuzzer/test/value-profile-load.test
Normal 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
|
||||
|
Loading…
Reference in New Issue
Block a user