[compiler-rt] r361448 - [libFuzzer] automatically collect the data flow trace (DFT) in the fork mode if -collect_data_flow= is given

Kostya Serebryany via llvm-commits llvm-commits at lists.llvm.org
Wed May 22 17:22:46 PDT 2019


Author: kcc
Date: Wed May 22 17:22:46 2019
New Revision: 361448

URL: http://llvm.org/viewvc/llvm-project?rev=361448&view=rev
Log:
[libFuzzer] automatically collect the data flow trace (DFT) in the fork mode if -collect_data_flow= is given

Added:
    compiler-rt/trunk/test/fuzzer/only-some-bytes-fork.test
Modified:
    compiler-rt/trunk/lib/fuzzer/FuzzerDataFlowTrace.cpp
    compiler-rt/trunk/lib/fuzzer/FuzzerDriver.cpp
    compiler-rt/trunk/lib/fuzzer/FuzzerFork.cpp
    compiler-rt/trunk/lib/fuzzer/FuzzerMerge.cpp
    compiler-rt/trunk/lib/fuzzer/FuzzerOptions.h

Modified: compiler-rt/trunk/lib/fuzzer/FuzzerDataFlowTrace.cpp
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/fuzzer/FuzzerDataFlowTrace.cpp?rev=361448&r1=361447&r2=361448&view=diff
==============================================================================
--- compiler-rt/trunk/lib/fuzzer/FuzzerDataFlowTrace.cpp (original)
+++ compiler-rt/trunk/lib/fuzzer/FuzzerDataFlowTrace.cpp Wed May 22 17:22:46 2019
@@ -174,6 +174,8 @@ bool DataFlowTrace::Init(const std::stri
     if (*FocusFunction == L)
       FocusFuncIdx = NumFunctions - 1;
   }
+  if (!NumFunctions)
+    return false;
 
   if (*FocusFunction == "auto") {
     // AUTOFOCUS works like this:

Modified: compiler-rt/trunk/lib/fuzzer/FuzzerDriver.cpp
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/fuzzer/FuzzerDriver.cpp?rev=361448&r1=361447&r2=361448&view=diff
==============================================================================
--- compiler-rt/trunk/lib/fuzzer/FuzzerDriver.cpp (original)
+++ compiler-rt/trunk/lib/fuzzer/FuzzerDriver.cpp Wed May 22 17:22:46 2019
@@ -700,6 +700,8 @@ int FuzzerDriver(int *argc, char ***argv
     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
   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));

Modified: compiler-rt/trunk/lib/fuzzer/FuzzerFork.cpp
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/fuzzer/FuzzerFork.cpp?rev=361448&r1=361447&r2=361448&view=diff
==============================================================================
--- compiler-rt/trunk/lib/fuzzer/FuzzerFork.cpp (original)
+++ compiler-rt/trunk/lib/fuzzer/FuzzerFork.cpp Wed May 22 17:22:46 2019
@@ -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 Fu
   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 Fu
   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());

Modified: compiler-rt/trunk/lib/fuzzer/FuzzerMerge.cpp
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/fuzzer/FuzzerMerge.cpp?rev=361448&r1=361447&r2=361448&view=diff
==============================================================================
--- compiler-rt/trunk/lib/fuzzer/FuzzerMerge.cpp (original)
+++ compiler-rt/trunk/lib/fuzzer/FuzzerMerge.cpp Wed May 22 17:22:46 2019
@@ -324,6 +324,7 @@ void CrashResistantMerge(const Vector<st
   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);

Modified: compiler-rt/trunk/lib/fuzzer/FuzzerOptions.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/fuzzer/FuzzerOptions.h?rev=361448&r1=361447&r2=361448&view=diff
==============================================================================
--- compiler-rt/trunk/lib/fuzzer/FuzzerOptions.h (original)
+++ compiler-rt/trunk/lib/fuzzer/FuzzerOptions.h Wed May 22 17:22:46 2019
@@ -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;

Added: compiler-rt/trunk/test/fuzzer/only-some-bytes-fork.test
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/fuzzer/only-some-bytes-fork.test?rev=361448&view=auto
==============================================================================
--- compiler-rt/trunk/test/fuzzer/only-some-bytes-fork.test (added)
+++ compiler-rt/trunk/test/fuzzer/only-some-bytes-fork.test Wed May 22 17:22:46 2019
@@ -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




More information about the llvm-commits mailing list