[llvm] r251168 - [libFuzzer] add -merge flag to merge corpora

Kostya Serebryany via llvm-commits llvm-commits at lists.llvm.org
Fri Oct 23 18:16:41 PDT 2015


Author: kcc
Date: Fri Oct 23 20:16:40 2015
New Revision: 251168

URL: http://llvm.org/viewvc/llvm-project?rev=251168&view=rev
Log:
[libFuzzer] add -merge flag to merge corpora

Added:
    llvm/trunk/lib/Fuzzer/test/merge.test
Modified:
    llvm/trunk/docs/LibFuzzer.rst
    llvm/trunk/lib/Fuzzer/FuzzerDriver.cpp
    llvm/trunk/lib/Fuzzer/FuzzerFlags.def
    llvm/trunk/lib/Fuzzer/FuzzerInternal.h
    llvm/trunk/lib/Fuzzer/FuzzerLoop.cpp

Modified: llvm/trunk/docs/LibFuzzer.rst
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/LibFuzzer.rst?rev=251168&r1=251167&r2=251168&view=diff
==============================================================================
--- llvm/trunk/docs/LibFuzzer.rst (original)
+++ llvm/trunk/docs/LibFuzzer.rst Fri Oct 23 20:16:40 2015
@@ -64,6 +64,7 @@ The most important flags are::
   max_total_time                        0       If positive, indicates the maximal total time in seconds to run the fuzzer.
   help                               	0	Print help.
   save_minimized_corpus              	0	If 1, the minimized corpus is saved into the first input directory. Example: ./fuzzer -save_minimized_corpus=1 NEW_EMPTY_DIR OLD_CORPUS
+  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.
   jobs                               	0	Number of jobs to run. If jobs >= 1 we spawn this number of jobs in separate worker processes with stdout/stderr redirected to fuzz-JOB.log.
   workers                            	0	Number of simultaneous worker processes to run the jobs. If zero, "min(jobs,NumberOfCpuCores()/2)" is used.
   sync_command                       	0	Execute an external command "<sync_command> <test_corpus>" to synchronize the test corpus.

Modified: llvm/trunk/lib/Fuzzer/FuzzerDriver.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/FuzzerDriver.cpp?rev=251168&r1=251167&r2=251168&view=diff
==============================================================================
--- llvm/trunk/lib/Fuzzer/FuzzerDriver.cpp (original)
+++ llvm/trunk/lib/Fuzzer/FuzzerDriver.cpp Fri Oct 23 20:16:40 2015
@@ -269,6 +269,11 @@ int FuzzerDriver(const std::vector<std::
   if (Flags.test_single_input)
     return RunOneTest(&F, Flags.test_single_input);
 
+  if (Flags.merge) {
+    F.Merge(*Inputs);
+    exit(0);
+  }
+
   unsigned Seed = Flags.seed;
   // Initialize Seed.
   if (Seed == 0)

Modified: llvm/trunk/lib/Fuzzer/FuzzerFlags.def
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/FuzzerFlags.def?rev=251168&r1=251167&r2=251168&view=diff
==============================================================================
--- llvm/trunk/lib/Fuzzer/FuzzerFlags.def (original)
+++ llvm/trunk/lib/Fuzzer/FuzzerFlags.def Fri Oct 23 20:16:40 2015
@@ -36,6 +36,8 @@ FUZZER_FLAG_INT(
     save_minimized_corpus, 0,
     "If 1, the minimized corpus is saved into the first input directory. "
     "Example: ./fuzzer -save_minimized_corpus=1 NEW_EMPTY_DIR OLD_CORPUS")
+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.")
 FUZZER_FLAG_INT(use_counters, 1, "Use coverage counters")
 FUZZER_FLAG_INT(use_indir_calls, 1, "Use indirect caller-callee counters")
 FUZZER_FLAG_INT(use_traces, 0, "Experimental: use instruction traces")

Modified: llvm/trunk/lib/Fuzzer/FuzzerInternal.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/FuzzerInternal.h?rev=251168&r1=251167&r2=251168&view=diff
==============================================================================
--- llvm/trunk/lib/Fuzzer/FuzzerInternal.h (original)
+++ llvm/trunk/lib/Fuzzer/FuzzerInternal.h Fri Oct 23 20:16:40 2015
@@ -104,6 +104,7 @@ class Fuzzer {
   void InitializeTraceState();
   size_t CorpusSize() const { return Corpus.size(); }
   void ReadDir(const std::string &Path, long *Epoch) {
+    Printf("Loading corpus: %s\n", Path.c_str());
     ReadDirToVectorOfUnits(Path.c_str(), &Corpus, Epoch);
   }
   void RereadOutputCorpus();
@@ -121,6 +122,9 @@ class Fuzzer {
 
   void ExecuteCallback(const Unit &U);
 
+  // Merge Corpora[1:] into Corpora[0].
+  void Merge(const std::vector<std::string> &Corpora);
+
  private:
   void AlarmCallback();
   void MutateAndTestOne(Unit *U);

Modified: llvm/trunk/lib/Fuzzer/FuzzerLoop.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/FuzzerLoop.cpp?rev=251168&r1=251167&r2=251168&view=diff
==============================================================================
--- llvm/trunk/lib/Fuzzer/FuzzerLoop.cpp (original)
+++ llvm/trunk/lib/Fuzzer/FuzzerLoop.cpp Fri Oct 23 20:16:40 2015
@@ -286,6 +286,38 @@ void Fuzzer::ReportNewCoverage(const Uni
     exit(0);
 }
 
+void Fuzzer::Merge(const std::vector<std::string> &Corpora) {
+  if (Corpora.size() <= 1) {
+    Printf("Merge requires two or more corpus dirs\n");
+    return;
+  }
+  auto InitialCorpusDir = Corpora[0];
+  ReadDir(InitialCorpusDir, nullptr);
+  Printf("Merge: running the initial corpus '%s' of %d units\n",
+         InitialCorpusDir.c_str(), Corpus.size());
+  for (auto &U : Corpus)
+    RunOne(U);
+
+  std::vector<std::string> ExtraCorpora(Corpora.begin() + 1, Corpora.end());
+
+  size_t NumTried = 0;
+  size_t NumMerged = 0;
+  for (auto &C : ExtraCorpora) {
+    Corpus.clear();
+    ReadDir(C, nullptr);
+    Printf("Merge: merging the extra corpus '%s' of %zd units\n", C.c_str(),
+           Corpus.size());
+    for (auto &U : Corpus) {
+      NumTried++;
+      if (RunOne(U)) {
+        WriteToOutputCorpus(U);
+        NumMerged++;
+      }
+    }
+  }
+  Printf("Merge: written %zd out of %zd units\n", NumMerged, NumTried);
+}
+
 void Fuzzer::MutateAndTestOne(Unit *U) {
   for (int i = 0; i < Options.MutateDepth; i++) {
     StartTraceRecording();

Added: llvm/trunk/lib/Fuzzer/test/merge.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/test/merge.test?rev=251168&view=auto
==============================================================================
--- llvm/trunk/lib/Fuzzer/test/merge.test (added)
+++ llvm/trunk/lib/Fuzzer/test/merge.test Fri Oct 23 20:16:40 2015
@@ -0,0 +1,29 @@
+CHECK: BINGO
+
+RUN: rm -rf  %tmp/T1 %tmp/T2
+RUN: mkdir -p %tmp/T1 %tmp/T2
+RUN: echo F..... > %tmp/T1/1
+RUN: echo .U.... > %tmp/T1/2
+RUN: echo ..Z... > %tmp/T1/3
+
+# T1 has 3 elements, T2 is empty.
+RUN: LLVMFuzzer-FullCoverageSetTest -merge=1 %tmp/T1 %tmp/T2 2>&1 | FileCheck %s --check-prefix=CHECK1
+CHECK1: Merge: running the initial corpus {{.*}} of 3 units
+CHECK1: Merge: written 0 out of 0 units
+
+RUN: echo ...Z.. > %tmp/T2/1
+RUN: echo ....E. > %tmp/T2/2
+RUN: echo .....R > %tmp/T2/3
+RUN: echo F..... > %tmp/T2/a
+RUN: echo .U.... > %tmp/T2/b
+RUN: echo ..Z... > %tmp/T2/c
+
+# T1 has 3 elements, T2 has 6 elements, only 3 are new.
+RUN: LLVMFuzzer-FullCoverageSetTest -merge=1 %tmp/T1 %tmp/T2 2>&1 | FileCheck %s --check-prefix=CHECK2
+CHECK2: Merge: running the initial corpus {{.*}} of 3 units
+CHECK2: Merge: written 3 out of 6 units
+
+# Now, T1 has 6 units and T2 has no new interesting units.
+RUN: LLVMFuzzer-FullCoverageSetTest -merge=1 %tmp/T1 %tmp/T2 2>&1 | FileCheck %s --check-prefix=CHECK3
+CHECK3: Merge: running the initial corpus {{.*}} of 6 units
+CHECK3: Merge: written 0 out of 6 units




More information about the llvm-commits mailing list