diff options
Diffstat (limited to 'compiler-rt/lib/fuzzer/FuzzerFork.cpp')
-rw-r--r-- | compiler-rt/lib/fuzzer/FuzzerFork.cpp | 72 |
1 files changed, 56 insertions, 16 deletions
diff --git a/compiler-rt/lib/fuzzer/FuzzerFork.cpp b/compiler-rt/lib/fuzzer/FuzzerFork.cpp index eff90094dae..09da1924b9b 100644 --- a/compiler-rt/lib/fuzzer/FuzzerFork.cpp +++ b/compiler-rt/lib/fuzzer/FuzzerFork.cpp @@ -17,6 +17,7 @@ #include "FuzzerUtil.h" #include <atomic> +#include <chrono> #include <fstream> #include <mutex> #include <queue> @@ -76,10 +77,22 @@ struct GlobalEnv { 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 @@ struct GlobalEnv { 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 WorkerThread(std::atomic<bool> *Stop, JobQueue *FuzzQ, JobQueue *MergeQ) { 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 @@ void FuzzWithFork(Random &Rand, const FuzzingOptions &Options, {}, &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 @@ void FuzzWithFork(Random &Rand, const FuzzingOptions &Options, 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 @@ void FuzzWithFork(Random &Rand, const FuzzingOptions &Options, // 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 @@ void FuzzWithFork(Random &Rand, const FuzzingOptions &Options, 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); } |