diff options
Diffstat (limited to 'compiler-rt/lib/fuzzer')
-rw-r--r-- | compiler-rt/lib/fuzzer/FuzzerDriver.cpp | 1 | ||||
-rw-r--r-- | compiler-rt/lib/fuzzer/FuzzerFlags.def | 1 | ||||
-rw-r--r-- | compiler-rt/lib/fuzzer/FuzzerFork.cpp | 72 | ||||
-rw-r--r-- | compiler-rt/lib/fuzzer/FuzzerIO.cpp | 2 | ||||
-rw-r--r-- | compiler-rt/lib/fuzzer/FuzzerIO.h | 2 | ||||
-rw-r--r-- | compiler-rt/lib/fuzzer/FuzzerIOPosix.cpp | 4 | ||||
-rw-r--r-- | compiler-rt/lib/fuzzer/FuzzerIOWindows.cpp | 2 | ||||
-rw-r--r-- | compiler-rt/lib/fuzzer/FuzzerOptions.h | 5 |
8 files changed, 66 insertions, 23 deletions
diff --git a/compiler-rt/lib/fuzzer/FuzzerDriver.cpp b/compiler-rt/lib/fuzzer/FuzzerDriver.cpp index 9f1621fcdb5..9c99d5ffb5e 100644 --- a/compiler-rt/lib/fuzzer/FuzzerDriver.cpp +++ b/compiler-rt/lib/fuzzer/FuzzerDriver.cpp @@ -606,6 +606,7 @@ int FuzzerDriver(int *argc, char ***argv, UserCallback Callback) { Options.TimeoutExitCode = Flags.timeout_exitcode; Options.IgnoreTimeouts = Flags.ignore_timeouts; Options.IgnoreOOMs = Flags.ignore_ooms; + Options.IgnoreCrashes = Flags.ignore_crashes; Options.MaxTotalTimeSec = Flags.max_total_time; Options.DoCrossOver = Flags.cross_over; Options.MutateDepth = Flags.mutate_depth; diff --git a/compiler-rt/lib/fuzzer/FuzzerFlags.def b/compiler-rt/lib/fuzzer/FuzzerFlags.def index d194a894f94..79eb75c3f8c 100644 --- a/compiler-rt/lib/fuzzer/FuzzerFlags.def +++ b/compiler-rt/lib/fuzzer/FuzzerFlags.def @@ -45,6 +45,7 @@ FUZZER_FLAG_INT(fork, 0, "Experimental mode where fuzzing happens " "in a subprocess") FUZZER_FLAG_INT(ignore_timeouts, 1, "Ignore timeouts in fork mode") FUZZER_FLAG_INT(ignore_ooms, 1, "Ignore OOMs in fork mode") +FUZZER_FLAG_INT(ignore_crashes, 0, "Ignore crashes in fork mode") 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.") 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); } diff --git a/compiler-rt/lib/fuzzer/FuzzerIO.cpp b/compiler-rt/lib/fuzzer/FuzzerIO.cpp index 33d6568c9c0..290112aa4b1 100644 --- a/compiler-rt/lib/fuzzer/FuzzerIO.cpp +++ b/compiler-rt/lib/fuzzer/FuzzerIO.cpp @@ -136,7 +136,7 @@ void VPrintf(bool Verbose, const char *Fmt, ...) { } void RmDirRecursive(const std::string &Dir) { - IterateDirRecurisve( + IterateDirRecursive( Dir, [](const std::string &Path) {}, [](const std::string &Path) { RmDir(Path); }, [](const std::string &Path) { RemoveFile(Path); }); diff --git a/compiler-rt/lib/fuzzer/FuzzerIO.h b/compiler-rt/lib/fuzzer/FuzzerIO.h index 588cf937935..e51b8d1b082 100644 --- a/compiler-rt/lib/fuzzer/FuzzerIO.h +++ b/compiler-rt/lib/fuzzer/FuzzerIO.h @@ -65,7 +65,7 @@ void RmDirRecursive(const std::string &Dir); // Iterate files and dirs inside Dir, recursively. // Call DirPreCallback/DirPostCallback on dirs before/after // calling FileCallback on files. -void IterateDirRecurisve(const std::string &Dir, +void IterateDirRecursive(const std::string &Dir, void (*DirPreCallback)(const std::string &Dir), void (*DirPostCallback)(const std::string &Dir), void (*FileCallback)(const std::string &Dir)); diff --git a/compiler-rt/lib/fuzzer/FuzzerIOPosix.cpp b/compiler-rt/lib/fuzzer/FuzzerIOPosix.cpp index 93eaad6c97f..92d19d3b69f 100644 --- a/compiler-rt/lib/fuzzer/FuzzerIOPosix.cpp +++ b/compiler-rt/lib/fuzzer/FuzzerIOPosix.cpp @@ -79,7 +79,7 @@ void ListFilesInDirRecursive(const std::string &Dir, long *Epoch, } -void IterateDirRecurisve(const std::string &Dir, +void IterateDirRecursive(const std::string &Dir, void (*DirPreCallback)(const std::string &Dir), void (*DirPostCallback)(const std::string &Dir), void (*FileCallback)(const std::string &Dir)) { @@ -94,7 +94,7 @@ void IterateDirRecurisve(const std::string &Dir, else if ((E->d_type == DT_DIR || (E->d_type == DT_UNKNOWN && IsDirectory(Path))) && *E->d_name != '.') - IterateDirRecurisve(Path, DirPreCallback, DirPostCallback, FileCallback); + IterateDirRecursive(Path, DirPreCallback, DirPostCallback, FileCallback); } closedir(D); DirPostCallback(Dir); diff --git a/compiler-rt/lib/fuzzer/FuzzerIOWindows.cpp b/compiler-rt/lib/fuzzer/FuzzerIOWindows.cpp index 00256ca25ef..e49e8a4c5f7 100644 --- a/compiler-rt/lib/fuzzer/FuzzerIOWindows.cpp +++ b/compiler-rt/lib/fuzzer/FuzzerIOWindows.cpp @@ -141,7 +141,7 @@ void ListFilesInDirRecursive(const std::string &Dir, long *Epoch, } -void IterateDirRecurisve(const std::string &Dir, +void IterateDirRecursive(const std::string &Dir, void (*DirPreCallback)(const std::string &Dir), void (*DirPostCallback)(const std::string &Dir), void (*FileCallback)(const std::string &Dir)) { diff --git a/compiler-rt/lib/fuzzer/FuzzerOptions.h b/compiler-rt/lib/fuzzer/FuzzerOptions.h index 628603ff520..7a607e8eec5 100644 --- a/compiler-rt/lib/fuzzer/FuzzerOptions.h +++ b/compiler-rt/lib/fuzzer/FuzzerOptions.h @@ -23,8 +23,9 @@ struct FuzzingOptions { int OOMExitCode = 71; int InterruptExitCode = 72; int ErrorExitCode = 77; - bool IgnoreTimeouts = 1; - bool IgnoreOOMs = 1; + bool IgnoreTimeouts = true; + bool IgnoreOOMs = true; + bool IgnoreCrashes = false; int MaxTotalTimeSec = 0; int RssLimitMb = 0; int MallocLimitMb = 0; |