diff options
-rw-r--r-- | compiler-rt/lib/fuzzer/FuzzerDataFlowTrace.cpp | 2 | ||||
-rw-r--r-- | compiler-rt/lib/fuzzer/FuzzerDriver.cpp | 4 | ||||
-rw-r--r-- | compiler-rt/lib/fuzzer/FuzzerFork.cpp | 36 | ||||
-rw-r--r-- | compiler-rt/lib/fuzzer/FuzzerMerge.cpp | 1 | ||||
-rw-r--r-- | compiler-rt/lib/fuzzer/FuzzerOptions.h | 1 | ||||
-rw-r--r-- | compiler-rt/test/fuzzer/only-some-bytes-fork.test | 12 |
6 files changed, 53 insertions, 3 deletions
diff --git a/compiler-rt/lib/fuzzer/FuzzerDataFlowTrace.cpp b/compiler-rt/lib/fuzzer/FuzzerDataFlowTrace.cpp index 975a98afc50..74bfa8f32df 100644 --- a/compiler-rt/lib/fuzzer/FuzzerDataFlowTrace.cpp +++ b/compiler-rt/lib/fuzzer/FuzzerDataFlowTrace.cpp @@ -174,6 +174,8 @@ bool DataFlowTrace::Init(const std::string &DirPath, if (*FocusFunction == L) FocusFuncIdx = NumFunctions - 1; } + if (!NumFunctions) + return false; if (*FocusFunction == "auto") { // AUTOFOCUS works like this: diff --git a/compiler-rt/lib/fuzzer/FuzzerDriver.cpp b/compiler-rt/lib/fuzzer/FuzzerDriver.cpp index 95ce8bbe994..d55caf4c6ec 100644 --- a/compiler-rt/lib/fuzzer/FuzzerDriver.cpp +++ b/compiler-rt/lib/fuzzer/FuzzerDriver.cpp @@ -700,6 +700,8 @@ int FuzzerDriver(int *argc, char ***argv, UserCallback Callback) { Options.DataFlowTrace = Flags.data_flow_trace; if (Flags.features_dir) Options.FeaturesDir = Flags.features_dir; + if (Flags.collect_data_flow) + Options.CollectDataFlow = Flags.collect_data_flow; Options.LazyCounters = Flags.lazy_counters; unsigned Seed = Flags.seed; @@ -710,7 +712,7 @@ int FuzzerDriver(int *argc, char ***argv, UserCallback Callback) { if (Flags.verbosity) Printf("INFO: Seed: %u\n", Seed); - if (Flags.collect_data_flow) { + if (Flags.collect_data_flow && !Flags.fork && !Flags.merge) { if (RunIndividualFiles) return CollectDataFlow(Flags.collect_data_flow, Flags.data_flow_trace, ReadCorpora({}, *Inputs)); diff --git a/compiler-rt/lib/fuzzer/FuzzerFork.cpp b/compiler-rt/lib/fuzzer/FuzzerFork.cpp index dd16ec1e288..870a2244850 100644 --- a/compiler-rt/lib/fuzzer/FuzzerFork.cpp +++ b/compiler-rt/lib/fuzzer/FuzzerFork.cpp @@ -86,6 +86,8 @@ struct GlobalEnv { Vector<std::string> CorpusDirs; std::string MainCorpusDir; std::string TempDir; + std::string DFTDir; + std::string DataFlowBinary; Set<uint32_t> Features, Cov; Vector<std::string> Files; Random *Rand; @@ -109,13 +111,18 @@ struct GlobalEnv { Command Cmd(Args); Cmd.removeFlag("fork"); Cmd.removeFlag("runs"); + Cmd.removeFlag("collect_data_flow"); for (auto &C : CorpusDirs) // Remove all corpora from the args. Cmd.removeArgument(C); Cmd.addFlag("reload", "0"); // working in an isolated dir, no reload. Cmd.addFlag("print_final_stats", "1"); Cmd.addFlag("print_funcs", "0"); // no need to spend time symbolizing. Cmd.addFlag("max_total_time", std::to_string(std::min((size_t)300, JobId))); - + if (!DataFlowBinary.empty()) { + Cmd.addFlag("data_flow_trace", DFTDir); + if (!Cmd.hasFlag("focus_function")) + Cmd.addFlag("focus_function", "auto"); + } auto Job = new FuzzJob; std::string Seeds; if (size_t CorpusSubsetSize = @@ -124,7 +131,8 @@ struct GlobalEnv { Seeds += (Seeds.empty() ? "" : ",") + Files[Rand->SkewTowardsLast(Files.size())]; if (!Seeds.empty()) { - Job->SeedListPath = std::to_string(JobId) + ".seeds"; + Job->SeedListPath = + DirPlusFile(TempDir, std::to_string(JobId) + ".seeds"); WriteToFile(Seeds, Job->SeedListPath); Cmd.addFlag("seed_inputs", "@" + Job->SeedListPath); } @@ -188,6 +196,7 @@ struct GlobalEnv { auto NewPath = DirPlusFile(MainCorpusDir, Hash(U)); WriteToFile(U, NewPath); Files.push_back(NewPath); + CollectDFT(NewPath); } Features.insert(NewFeatures.begin(), NewFeatures.end()); Cov.insert(NewCov.begin(), NewCov.end()); @@ -204,6 +213,23 @@ struct GlobalEnv { Stats.average_exec_per_sec, NumOOMs, NumTimeouts, NumCrashes, secondsSinceProcessStartUp()); } + + + void CollectDFT(const std::string &InputPath) { + if (DataFlowBinary.empty()) return; + Command Cmd(Args); + Cmd.removeFlag("fork"); + Cmd.removeFlag("runs"); + Cmd.addFlag("data_flow_trace", DFTDir); + Cmd.addArgument(InputPath); + for (auto &C : CorpusDirs) // Remove all corpora from the args. + Cmd.removeArgument(C); + Cmd.setOutputFile(DirPlusFile(TempDir, "dft.log")); + Cmd.combineOutAndErr(); + // Printf("CollectDFT: %s %s\n", InputPath.c_str(), Cmd.toString().c_str()); + ExecuteCommand(Cmd); + } + }; struct JobQueue { @@ -248,14 +274,17 @@ void FuzzWithFork(Random &Rand, const FuzzingOptions &Options, Env.Rand = &Rand; Env.Verbosity = Options.Verbosity; Env.ProcessStartTime = std::chrono::system_clock::now(); + Env.DataFlowBinary = Options.CollectDataFlow; Vector<SizedFile> SeedFiles; for (auto &Dir : CorpusDirs) GetSizedFilesFromDir(Dir, &SeedFiles); std::sort(SeedFiles.begin(), SeedFiles.end()); Env.TempDir = TempPath(".dir"); + Env.DFTDir = DirPlusFile(Env.TempDir, "DFT"); RmDirRecursive(Env.TempDir); // in case there is a leftover from old runs. MkDir(Env.TempDir); + MkDir(Env.DFTDir); if (CorpusDirs.empty()) @@ -267,6 +296,9 @@ void FuzzWithFork(Random &Rand, const FuzzingOptions &Options, CrashResistantMerge(Env.Args, {}, SeedFiles, &Env.Files, {}, &Env.Features, {}, &Env.Cov, CFPath, false); + for (auto &F : Env.Files) + Env.CollectDFT(F); + RemoveFile(CFPath); Printf("INFO: -fork=%d: %zd seed inputs, starting to fuzz in %s\n", NumJobs, Env.Files.size(), Env.TempDir.c_str()); diff --git a/compiler-rt/lib/fuzzer/FuzzerMerge.cpp b/compiler-rt/lib/fuzzer/FuzzerMerge.cpp index dace45ece1d..75b2b5d59b9 100644 --- a/compiler-rt/lib/fuzzer/FuzzerMerge.cpp +++ b/compiler-rt/lib/fuzzer/FuzzerMerge.cpp @@ -324,6 +324,7 @@ void CrashResistantMerge(const Vector<std::string> &Args, Command BaseCmd(Args); BaseCmd.removeFlag("merge"); BaseCmd.removeFlag("fork"); + BaseCmd.removeFlag("collect_data_flow"); for (size_t Attempt = 1; Attempt <= NumAttempts; Attempt++) { Fuzzer::MaybeExitGracefully(); VPrintf(V, "MERGE-OUTER: attempt %zd\n", Attempt); diff --git a/compiler-rt/lib/fuzzer/FuzzerOptions.h b/compiler-rt/lib/fuzzer/FuzzerOptions.h index d48439daaf4..687f2ffa732 100644 --- a/compiler-rt/lib/fuzzer/FuzzerOptions.h +++ b/compiler-rt/lib/fuzzer/FuzzerOptions.h @@ -51,6 +51,7 @@ struct FuzzingOptions { std::string ExitOnItem; std::string FocusFunction; std::string DataFlowTrace; + std::string CollectDataFlow; std::string FeaturesDir; bool SaveArtifacts = true; bool PrintNEW = true; // Print a status line when new units are found; diff --git a/compiler-rt/test/fuzzer/only-some-bytes-fork.test b/compiler-rt/test/fuzzer/only-some-bytes-fork.test new file mode 100644 index 00000000000..4eb048294c9 --- /dev/null +++ b/compiler-rt/test/fuzzer/only-some-bytes-fork.test @@ -0,0 +1,12 @@ +# Tests the data flow tracer. +REQUIRES: linux, x86_64 + +# Build the tracer and the test. +RUN: %no_fuzzer_cpp_compiler -c -fno-sanitize=all -fsanitize=dataflow %S/../../lib/fuzzer/dataflow/DataFlow.cpp -o %t-DataFlow.o +RUN: %no_fuzzer_cpp_compiler -fno-sanitize=all -fsanitize=dataflow -fsanitize-coverage=trace-pc-guard,pc-table,bb,trace-cmp %S/OnlySomeBytesTest.cpp %t-DataFlow.o -o %t-DFT +RUN: %cpp_compiler %S/OnlySomeBytesTest.cpp -o %t-Fuzz + +# Test that the fork mode can collect and use the DFT +RUN: rm -rf %t && mkdir %t +RUN: not %t-Fuzz -collect_data_flow=%t-DFT -use_value_profile=1 -runs=100000000 -fork=1 2> %t/log +RUN: grep BINGO %t/log |