[libFuzzer] form mode: add -ignore_crashes flag, honor the max_total_time flag, print the number of ooms/timeouts/crashes, fix a typo
git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk/lib/fuzzer@354175 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/FuzzerFork.cpp b/FuzzerFork.cpp
index eff9009..09da192 100644
--- a/FuzzerFork.cpp
+++ b/FuzzerFork.cpp
@@ -17,6 +17,7 @@
#include "FuzzerUtil.h"
#include <atomic>
+#include <chrono>
#include <fstream>
#include <mutex>
#include <queue>
@@ -76,10 +77,22 @@
Set<uint32_t> Features, Cov;
Vector<std::string> Files;
Random *Rand;
+ std::chrono::system_clock::time_point ProcessStartTime;
int Verbosity = 0;
+ size_t NumTimeouts = 0;
+ size_t NumOOMs = 0;
+ size_t NumCrashes = 0;
+
+
size_t NumRuns = 0;
+ size_t secondsSinceProcessStartUp() const {
+ return std::chrono::duration_cast<std::chrono::seconds>(
+ std::chrono::system_clock::now() - ProcessStartTime)
+ .count();
+ }
+
FuzzJob *CreateNewJob(size_t JobId) {
Command Cmd(Args);
Cmd.removeFlag("fork");
@@ -146,10 +159,12 @@
auto Stats = ParseFinalStatsFromLog(Job->LogPath);
NumRuns += Stats.number_of_executed_units;
- if (!FilesToAdd.empty())
- Printf("#%zd: cov: %zd ft: %zd corp: %zd exec/s %zd\n", NumRuns,
+ if (!FilesToAdd.empty() || Job->ExitCode != 0)
+ Printf("#%zd: cov: %zd ft: %zd corp: %zd exec/s %zd "
+ "oom/timeout/crash: %zd/%zd/%zd time: %zds\n", NumRuns,
Cov.size(), Features.size(), Files.size(),
- Stats.average_exec_per_sec);
+ Stats.average_exec_per_sec,
+ NumOOMs, NumTimeouts, NumCrashes, secondsSinceProcessStartUp());
}
};
@@ -187,14 +202,14 @@
void FuzzWithFork(Random &Rand, const FuzzingOptions &Options,
const Vector<std::string> &Args,
const Vector<std::string> &CorpusDirs, int NumJobs) {
- Printf("INFO: -fork=%d: doing fuzzing in a separate process in order to "
- "be more resistant to crashes, timeouts, and OOMs\n", NumJobs);
+ Printf("INFO: -fork=%d: fuzzing in separate process(s)\n", NumJobs);
GlobalEnv Env;
Env.Args = Args;
Env.CorpusDirs = CorpusDirs;
Env.Rand = &Rand;
Env.Verbosity = Options.Verbosity;
+ Env.ProcessStartTime = std::chrono::system_clock::now();
Vector<SizedFile> SeedFiles;
for (auto &Dir : CorpusDirs)
@@ -215,8 +230,8 @@
{}, &Env.Cov,
CFPath, false);
RemoveFile(CFPath);
- Printf("INFO: -fork=%d: %zd seeds, starting to fuzz; scratch: %s\n",
- NumJobs, Env.Files.size(), Env.TempDir.c_str());
+ Printf("INFO: -fork=%d: %zd seed inputs, starting to fuzz in %s\n", NumJobs,
+ Env.Files.size(), Env.TempDir.c_str());
int ExitCode = 0;
@@ -230,9 +245,11 @@
FuzzQ.Push(Env.CreateNewJob(JobId++));
}
- while (!Stop) {
+ while (true) {
auto Job = MergeQ.Pop();
if (!Job) {
+ if (Stop)
+ break;
SleepSeconds(1);
continue;
}
@@ -242,20 +259,42 @@
// Continue if our crash is one of the ignorred ones.
if (Options.IgnoreTimeouts && ExitCode == Options.TimeoutExitCode)
- ;
+ Env.NumTimeouts++;
else if (Options.IgnoreOOMs && ExitCode == Options.OOMExitCode)
- ;
+ Env.NumOOMs++;
else if (ExitCode == Options.InterruptExitCode)
Stop = true;
else if (ExitCode != 0) {
- // And exit if we don't ignore this crash.
- Printf("INFO: log from the inner process:\n%s",
- FileToString(Job->LogPath).c_str());
- Stop = true;
+ Env.NumCrashes++;
+ if (Options.IgnoreCrashes) {
+ std::ifstream In(Job->LogPath);
+ std::string Line;
+ while (std::getline(In, Line, '\n'))
+ if (Line.find("ERROR:") != Line.npos)
+ Printf("%s\n", Line.c_str());
+ } else {
+ // And exit if we don't ignore this crash.
+ Printf("INFO: log from the inner process:\n%s",
+ FileToString(Job->LogPath).c_str());
+ Stop = true;
+ }
}
RemoveFile(Job->LogPath);
delete Job;
- FuzzQ.Push(Env.CreateNewJob(JobId++));
+
+ // Stop if we are over the time budget.
+ // This is not precise, since other threads are still running
+ // and we will wait while joining them.
+ // We also don't stop instantly: other jobs need to finish.
+ if (Options.MaxTotalTimeSec > 0 && !Stop &&
+ Env.secondsSinceProcessStartUp() >= (size_t)Options.MaxTotalTimeSec) {
+ Printf("INFO: fuzzed for %zd seconds, wrapping up soon\n",
+ Env.secondsSinceProcessStartUp());
+ Stop = true;
+ }
+
+ if (!Stop)
+ FuzzQ.Push(Env.CreateNewJob(JobId++));
}
Stop = true;
@@ -265,7 +304,8 @@
RmDirRecursive(Env.TempDir);
// Use the exit code from the last child process.
- Printf("Fork: exiting: %d\n", ExitCode);
+ Printf("INFO: exiting: %d time: %zds\n", ExitCode,
+ Env.secondsSinceProcessStartUp());
exit(ExitCode);
}