#include "FuzzerInternal.h"
-#include <climits>
#include <cstring>
#include <unistd.h>
#include <iostream>
-
-// ASAN options:
-// * don't dump the coverage to disk.
-extern "C" const char* __asan_default_options() { return "coverage_pcs=0"; }
+#include <thread>
+#include <atomic>
+#include <mutex>
// Program arguments.
struct FlagDescription {
}
}
+static void WorkerThread(const std::string &Cmd, std::atomic<int> *Counter,
+ int NumJobs, std::atomic<bool> *HasErrors) {
+ static std::mutex CerrMutex;
+ while (true) {
+ int C = (*Counter)++;
+ if (C >= NumJobs) break;
+ std::string Log = "fuzz-" + std::to_string(C) + ".log";
+ std::string ToRun = Cmd + " > " + Log + " 2>&1\n";
+ if (Flags.verbosity)
+ std::cerr << ToRun;
+ int ExitCode = system(ToRun.c_str());
+ if (ExitCode != 0)
+ *HasErrors = true;
+ std::lock_guard<std::mutex> Lock(CerrMutex);
+ std::cerr << "================== Job " << C
+ << " exited with exit code " << ExitCode
+ << " =================\n";
+ fuzzer::CopyFileToErr(Log);
+ }
+}
+
+static int RunInMultipleProcesses(int argc, char **argv, int NumWorkers,
+ int NumJobs) {
+ std::atomic<int> Counter(0);
+ std::atomic<bool> HasErrors(false);
+ std::string Cmd;
+ for (int i = 0; i < argc; i++) {
+ if (FlagValue(argv[i], "jobs") || FlagValue(argv[i], "workers")) continue;
+ Cmd += argv[i];
+ Cmd += " ";
+ }
+ std::vector<std::thread> V;
+ for (int i = 0; i < NumWorkers; i++)
+ V.push_back(std::thread(WorkerThread, Cmd, &Counter, NumJobs, &HasErrors));
+ for (auto &T : V)
+ T.join();
+ return HasErrors ? 1 : 0;
+}
+
int main(int argc, char **argv) {
using namespace fuzzer;
PrintHelp();
return 0;
}
+
+ if (Flags.workers > 0 && Flags.jobs > 0)
+ return RunInMultipleProcesses(argc, argv, Flags.workers, Flags.jobs);
+
Fuzzer::FuzzingOptions Options;
Options.Verbosity = Flags.verbosity;
Options.MaxLen = Flags.max_len;
Options.DoCrossOver = Flags.cross_over;
Options.MutateDepth = Flags.mutate_depth;
Options.ExitOnFirst = Flags.exit_on_first;
+ Options.UseFullCoverageSet = Flags.use_full_coverage_set;
+ Options.PreferSmallDuringInitialShuffle =
+ Flags.prefer_small_during_initial_shuffle;
+ if (Flags.runs >= 0)
+ Options.MaxNumberOfRuns = Flags.runs;
if (!inputs.empty())
Options.OutputCorpus = inputs[0];
Fuzzer F(Options);
if (F.CorpusSize() == 0)
F.AddToCorpus(Unit()); // Can't fuzz empty corpus, so add an empty input.
F.ShuffleAndMinimize();
+ if (Flags.save_minimized_corpus)
+ F.SaveCorpus();
F.Loop(Flags.iterations < 0 ? INT_MAX : Flags.iterations);
if (Flags.verbosity)
- std::cerr << "Done\n";
- return 1;
+ std::cerr << "Done " << F.getTotalNumberOfRuns()
+ << " runs in " << F.secondsSinceProcessStartUp()
+ << " seconds\n";
+ return 0;
}