[llvm] r257736 - [libFuzzer] suggest a dictionary to the user of some of the trace-based dictionary entries were successful

Kostya Serebryany via llvm-commits llvm-commits at lists.llvm.org
Wed Jan 13 18:36:45 PST 2016


Author: kcc
Date: Wed Jan 13 20:36:44 2016
New Revision: 257736

URL: http://llvm.org/viewvc/llvm-project?rev=257736&view=rev
Log:
[libFuzzer] suggest a dictionary to the user of some of the trace-based dictionary entries were successful

Added:
    llvm/trunk/lib/Fuzzer/test/RepeatedMemcmp.cpp
Modified:
    llvm/trunk/lib/Fuzzer/FuzzerInterface.h
    llvm/trunk/lib/Fuzzer/FuzzerLoop.cpp
    llvm/trunk/lib/Fuzzer/FuzzerMutate.cpp
    llvm/trunk/lib/Fuzzer/test/CMakeLists.txt
    llvm/trunk/lib/Fuzzer/test/FuzzerUnittest.cpp
    llvm/trunk/lib/Fuzzer/test/MemcmpTest.cpp
    llvm/trunk/lib/Fuzzer/test/fuzzer-dfsan.test
    llvm/trunk/lib/Fuzzer/test/fuzzer-traces.test

Modified: llvm/trunk/lib/Fuzzer/FuzzerInterface.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/FuzzerInterface.h?rev=257736&r1=257735&r2=257736&view=diff
==============================================================================
--- llvm/trunk/lib/Fuzzer/FuzzerInterface.h (original)
+++ llvm/trunk/lib/Fuzzer/FuzzerInterface.h Wed Jan 13 20:36:44 2016
@@ -76,6 +76,8 @@ class MutationDispatcher {
   void StartMutationSequence();
   /// Print the current sequence of mutations.
   void PrintMutationSequence();
+  /// Indicate that the current sequence of mutations was successfull.
+  void RecordSuccessfulMutationSequence();
   /// Mutates data by shuffling bytes.
   size_t Mutate_ShuffleBytes(uint8_t *Data, size_t Size, size_t MaxSize);
   /// Mutates data by erasing a byte.
@@ -91,9 +93,13 @@ class MutationDispatcher {
   size_t Mutate_AddWordFromManualDictionary(uint8_t *Data, size_t Size,
                                             size_t MaxSize);
 
-  /// Mutates data by adding a word from the automatic dictionary.
-  size_t Mutate_AddWordFromAutoDictionary(uint8_t *Data, size_t Size,
-                                          size_t MaxSize);
+  /// Mutates data by adding a word from the temporary automatic dictionary.
+  size_t Mutate_AddWordFromTemporaryAutoDictionary(uint8_t *Data, size_t Size,
+                                                   size_t MaxSize);
+
+  /// Mutates data by adding a word from the persistent automatic dictionary.
+  size_t Mutate_AddWordFromPersistentAutoDictionary(uint8_t *Data, size_t Size,
+                                                    size_t MaxSize);
 
   /// Tries to find an ASCII integer in Data, changes it to another ASCII int.
   size_t Mutate_ChangeASCIIInteger(uint8_t *Data, size_t Size, size_t MaxSize);
@@ -113,6 +119,7 @@ class MutationDispatcher {
 
   void AddWordToAutoDictionary(const Unit &Word, size_t PositionHint);
   void ClearAutoDictionary();
+  void PrintRecommendedDictionary();
 
   void SetCorpus(const std::vector<Unit> *Corpus);
 
@@ -157,8 +164,6 @@ class UserSuppliedFuzzer {
   UserSuppliedFuzzer(FuzzerRandomBase *Rand);
   /// Executes the target function on 'Size' bytes of 'Data'.
   virtual int TargetFunction(const uint8_t *Data, size_t Size) = 0;
-  virtual void StartMutationSequence() { MD.StartMutationSequence(); }
-  virtual void PrintMutationSequence() { MD.PrintMutationSequence(); }
   virtual void SetCorpus(const std::vector<Unit> *Corpus) {
     MD.SetCorpus(Corpus);
   }

Modified: llvm/trunk/lib/Fuzzer/FuzzerLoop.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/FuzzerLoop.cpp?rev=257736&r1=257735&r2=257736&view=diff
==============================================================================
--- llvm/trunk/lib/Fuzzer/FuzzerLoop.cpp (original)
+++ llvm/trunk/lib/Fuzzer/FuzzerLoop.cpp Wed Jan 13 20:36:44 2016
@@ -340,7 +340,7 @@ void Fuzzer::PrintStatusForNewUnit(const
   PrintStats("NEW   ", "");
   if (Options.Verbosity) {
     Printf(" L: %zd ", U.size());
-    USF.PrintMutationSequence();
+    USF.GetMD().PrintMutationSequence();
     Printf("\n");
   }
 }
@@ -348,6 +348,7 @@ void Fuzzer::PrintStatusForNewUnit(const
 void Fuzzer::ReportNewCoverage(const Unit &U) {
   Corpus.push_back(U);
   UnitHashesAddedToCorpus.insert(Hash(U));
+  USF.GetMD().RecordSuccessfulMutationSequence();
   PrintStatusForNewUnit(U);
   WriteToOutputCorpus(U);
   if (Options.ExitOnFirst)
@@ -387,7 +388,7 @@ void Fuzzer::Merge(const std::vector<std
 }
 
 void Fuzzer::MutateAndTestOne() {
-  USF.StartMutationSequence();
+  USF.GetMD().StartMutationSequence();
 
   auto U = ChooseUnitToMutate();
 
@@ -496,6 +497,7 @@ void Fuzzer::Loop() {
   }
 
   PrintStats("DONE  ", "\n");
+  USF.GetMD().PrintRecommendedDictionary();
 }
 
 void Fuzzer::SyncCorpus() {

Modified: llvm/trunk/lib/Fuzzer/FuzzerMutate.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/FuzzerMutate.cpp?rev=257736&r1=257735&r2=257736&view=diff
==============================================================================
--- llvm/trunk/lib/Fuzzer/FuzzerMutate.cpp (original)
+++ llvm/trunk/lib/Fuzzer/FuzzerMutate.cpp Wed Jan 13 20:36:44 2016
@@ -27,12 +27,28 @@ struct DictionaryEntry {
   size_t PositionHint;
 };
 
+struct Dictionary : public std::vector<DictionaryEntry>{
+  bool ContainsWord(const Unit &W) const {
+    return end() !=
+           std::find_if(begin(), end(), [&](const DictionaryEntry &DE) {
+             return DE.Word == W;
+           });
+  }
+};
+
 struct MutationDispatcher::Impl {
-  std::vector<DictionaryEntry> ManualDictionary;
-  std::vector<DictionaryEntry> AutoDictionary;
+  // Dictionary provided by the user via -dict=DICT_FILE.
+  Dictionary ManualDictionary;
+  // Temporary dictionary modified by the fuzzer itself,
+  // recreated periodically.
+  Dictionary TempAutoDictionary;
+  // Persistent dictionary modified by the fuzzer, consists of
+  // entries that led to successfull discoveries in the past mutations.
+  Dictionary PersistentAutoDictionary;
+
   std::vector<Mutator> Mutators;
   std::vector<Mutator> CurrentMutatorSequence;
-  std::vector<DictionaryEntry> CurrentDictionaryEntrySequence;
+  Dictionary CurrentDictionaryEntrySequence;
   const std::vector<Unit> *Corpus = nullptr;
   FuzzerRandomBase &Rand;
 
@@ -47,8 +63,10 @@ struct MutationDispatcher::Impl {
     Add({&MutationDispatcher::Mutate_CrossOver, "CrossOver"});
     Add({&MutationDispatcher::Mutate_AddWordFromManualDictionary,
          "AddFromManualDict"});
-    Add({&MutationDispatcher::Mutate_AddWordFromAutoDictionary,
-         "AddFromAutoDict"});
+    Add({&MutationDispatcher::Mutate_AddWordFromTemporaryAutoDictionary,
+         "AddFromTempAutoDict"});
+    Add({&MutationDispatcher::Mutate_AddWordFromPersistentAutoDictionary,
+         "AddFromPersAutoDict"});
   }
   void SetCorpus(const std::vector<Unit> *Corpus) { this->Corpus = Corpus; }
   size_t AddWordFromDictionary(const std::vector<DictionaryEntry> &D,
@@ -126,10 +144,15 @@ size_t MutationDispatcher::Mutate_AddWor
                                        MaxSize);
 }
 
-size_t MutationDispatcher::Mutate_AddWordFromAutoDictionary(uint8_t *Data,
-                                                            size_t Size,
-                                                            size_t MaxSize) {
-  return MDImpl->AddWordFromDictionary(MDImpl->AutoDictionary, Data, Size,
+size_t MutationDispatcher::Mutate_AddWordFromTemporaryAutoDictionary(
+    uint8_t *Data, size_t Size, size_t MaxSize) {
+  return MDImpl->AddWordFromDictionary(MDImpl->TempAutoDictionary, Data, Size,
+                                       MaxSize);
+}
+
+size_t MutationDispatcher::Mutate_AddWordFromPersistentAutoDictionary(
+    uint8_t *Data, size_t Size, size_t MaxSize) {
+  return MDImpl->AddWordFromDictionary(MDImpl->PersistentAutoDictionary, Data, Size,
                                        MaxSize);
 }
 
@@ -211,13 +234,36 @@ void MutationDispatcher::StartMutationSe
   MDImpl->CurrentDictionaryEntrySequence.clear();
 }
 
+// Copy successful dictionary entries to PersistentAutoDictionary.
+void MutationDispatcher::RecordSuccessfulMutationSequence() {
+  for (auto &DE : MDImpl->CurrentDictionaryEntrySequence)
+    // Linear search is fine here as this happens seldom.
+    if (!MDImpl->PersistentAutoDictionary.ContainsWord(DE.Word))
+      MDImpl->PersistentAutoDictionary.push_back(
+          {DE.Word, std::numeric_limits<size_t>::max()});
+}
+
+void MutationDispatcher::PrintRecommendedDictionary() {
+  std::vector<Unit> V;
+  for (auto &DE : MDImpl->PersistentAutoDictionary)
+    if (!MDImpl->ManualDictionary.ContainsWord(DE.Word))
+      V.push_back(DE.Word);
+  if (V.empty()) return;
+  Printf("###### Recommended dictionary. ######\n");
+  for (auto &U: V) {
+    Printf("\"");
+    PrintASCII(U, "\"\n");
+  }
+  Printf("###### End of recommended dictionary. ######\n");
+}
+
 void MutationDispatcher::PrintMutationSequence() {
   Printf("MS: %zd ", MDImpl->CurrentMutatorSequence.size());
   for (auto M : MDImpl->CurrentMutatorSequence)
     Printf("%s-", M.Name);
   if (!MDImpl->CurrentDictionaryEntrySequence.empty()) {
     Printf(" DE: ");
-    for (auto DE : MDImpl->CurrentDictionaryEntrySequence) {
+    for (auto &DE : MDImpl->CurrentDictionaryEntrySequence) {
       Printf("\"");
       PrintASCII(DE.Word, "\"-");
     }
@@ -261,12 +307,12 @@ void MutationDispatcher::AddWordToManual
 void MutationDispatcher::AddWordToAutoDictionary(const Unit &Word,
                                                  size_t PositionHint) {
   static const size_t kMaxAutoDictSize = 1 << 14;
-  if (MDImpl->AutoDictionary.size() >= kMaxAutoDictSize) return;
-  MDImpl->AutoDictionary.push_back({Word, PositionHint});
+  if (MDImpl->TempAutoDictionary.size() >= kMaxAutoDictSize) return;
+  MDImpl->TempAutoDictionary.push_back({Word, PositionHint});
 }
 
 void MutationDispatcher::ClearAutoDictionary() {
-  MDImpl->AutoDictionary.clear();
+  MDImpl->TempAutoDictionary.clear();
 }
 
 MutationDispatcher::MutationDispatcher(FuzzerRandomBase &Rand) : Rand(Rand) {

Modified: llvm/trunk/lib/Fuzzer/test/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/test/CMakeLists.txt?rev=257736&r1=257735&r2=257736&view=diff
==============================================================================
--- llvm/trunk/lib/Fuzzer/test/CMakeLists.txt (original)
+++ llvm/trunk/lib/Fuzzer/test/CMakeLists.txt Wed Jan 13 20:36:44 2016
@@ -20,6 +20,7 @@ set(Tests
   FullCoverageSetTest
   MemcmpTest
   NullDerefTest
+  RepeatedMemcmp
   SimpleCmpTest
   SimpleDictionaryTest
   SimpleHashTest

Modified: llvm/trunk/lib/Fuzzer/test/FuzzerUnittest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/test/FuzzerUnittest.cpp?rev=257736&r1=257735&r2=257736&view=diff
==============================================================================
--- llvm/trunk/lib/Fuzzer/test/FuzzerUnittest.cpp (original)
+++ llvm/trunk/lib/Fuzzer/test/FuzzerUnittest.cpp Wed Jan 13 20:36:44 2016
@@ -302,7 +302,7 @@ void TestAddWordFromDictionaryWithHint(M
 
 TEST(FuzzerMutate, AddWordFromDictionaryWithHint1) {
   TestAddWordFromDictionaryWithHint(
-      &MutationDispatcher::Mutate_AddWordFromAutoDictionary, 1 << 5);
+      &MutationDispatcher::Mutate_AddWordFromTemporaryAutoDictionary, 1 << 5);
 }
 
 TEST(FuzzerMutate, AddWordFromDictionaryWithHint2) {

Modified: llvm/trunk/lib/Fuzzer/test/MemcmpTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/test/MemcmpTest.cpp?rev=257736&r1=257735&r2=257736&view=diff
==============================================================================
--- llvm/trunk/lib/Fuzzer/test/MemcmpTest.cpp (original)
+++ llvm/trunk/lib/Fuzzer/test/MemcmpTest.cpp Wed Jan 13 20:36:44 2016
@@ -9,7 +9,7 @@ extern "C" int LLVMFuzzerTestOneInput(co
   if (Size >= 8 && memcmp(Data, "01234567", 8) == 0) {
     if (Size >= 12 && memcmp(Data + 8, "ABCD", 4) == 0) {
       if (Size >= 14 && memcmp(Data + 12, "XY", 2) == 0) {
-        if (Size >= 16 && memcmp(Data + 14, "KLM", 3) == 0) {
+        if (Size >= 17 && memcmp(Data + 14, "KLM", 3) == 0) {
           if (Size >= 27 && memcmp(Data + 17, "ABCDE-GHIJ", 10) == 0){
             fprintf(stderr, "BINGO %zd\n", Size);
             for (size_t i = 0; i < Size; i++) {

Added: llvm/trunk/lib/Fuzzer/test/RepeatedMemcmp.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/test/RepeatedMemcmp.cpp?rev=257736&view=auto
==============================================================================
--- llvm/trunk/lib/Fuzzer/test/RepeatedMemcmp.cpp (added)
+++ llvm/trunk/lib/Fuzzer/test/RepeatedMemcmp.cpp Wed Jan 13 20:36:44 2016
@@ -0,0 +1,19 @@
+
+#include <cstring>
+#include <cstdint>
+#include <cstdio>
+#include <cstdlib>
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+  int Matches = 0;
+  for (size_t i = 0; i + 2 < Size; i += 3) {
+    const char *Pat = i % 2 ? "foo" : "bar";
+    if (!memcmp(Data + i, Pat, 3))
+      Matches++;
+  }
+  if (Matches > 20) {
+    fprintf(stderr, "BINGO!\n");
+    exit(1);
+  }
+  return 0;
+}

Modified: llvm/trunk/lib/Fuzzer/test/fuzzer-dfsan.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/test/fuzzer-dfsan.test?rev=257736&r1=257735&r2=257736&view=diff
==============================================================================
--- llvm/trunk/lib/Fuzzer/test/fuzzer-dfsan.test (original)
+++ llvm/trunk/lib/Fuzzer/test/fuzzer-dfsan.test Wed Jan 13 20:36:44 2016
@@ -10,7 +10,7 @@ CHECK_DFSanMemcmpCallback: DFSanMemcmpCa
 RUN: not LLVMFuzzer-SimpleCmpTest-DFSan -use_traces=1 -seed=1 -runs=1000000 -timeout=5 2>&1 | FileCheck %s --check-prefix=CHECK1
 RUN: LLVMFuzzer-SimpleCmpTest-DFSan -use_traces=1 -seed=1 -runs=100 -timeout=5 -verbosity=3 2>&1 | FileCheck %s  -check-prefix=CHECK_DFSanCmpCallback
 
-RUN: not LLVMFuzzer-MemcmpTest-DFSan -use_traces=1 -seed=1 -runs=10000 -timeout=5 2>&1 | FileCheck %s --check-prefix=CHECK2
+RUN: not LLVMFuzzer-MemcmpTest-DFSan -use_traces=1 -seed=1 -runs=100000 -timeout=5 2>&1 | FileCheck %s --check-prefix=CHECK2
 RUN: LLVMFuzzer-MemcmpTest-DFSan -use_traces=1 -seed=1 -runs=2 -timeout=5 -verbosity=3 2>&1 | FileCheck %s  -check-prefix=CHECK_DFSanMemcmpCallback
 
 RUN: not LLVMFuzzer-StrncmpTest-DFSan -use_traces=1 -seed=1 -runs=10000 -timeout=5 2>&1 | FileCheck %s --check-prefix=CHECK3

Modified: llvm/trunk/lib/Fuzzer/test/fuzzer-traces.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/test/fuzzer-traces.test?rev=257736&r1=257735&r2=257736&view=diff
==============================================================================
--- llvm/trunk/lib/Fuzzer/test/fuzzer-traces.test (original)
+++ llvm/trunk/lib/Fuzzer/test/fuzzer-traces.test Wed Jan 13 20:36:44 2016
@@ -18,3 +18,10 @@ RUN:     LLVMFuzzer-SwitchTest
 
 RUN: not LLVMFuzzer-SimpleHashTest -use_traces=1 -seed=1 -runs=10000000  2>&1 | FileCheck %s
 RUN:     LLVMFuzzer-SimpleHashTest               -seed=1 -runs=10000000 2>&1 | FileCheck %s --check-prefix=Done10000000
+
+RUN: LLVMFuzzer-RepeatedMemcmp -use_traces=1 -seed=1 -runs=100000 2>&1 | FileCheck %s --check-prefix=RECOMMENDED_DICT
+RECOMMENDED_DICT:###### Recommended dictionary. ######
+RECOMMENDED_DICT-DAG: "foo"
+RECOMMENDED_DICT-DAG: "bar"
+RECOMMENDED_DICT:###### End of recommended dictionary. ######
+




More information about the llvm-commits mailing list