[llvm] r257013 - [libFuzzer] add a position hint to the dictionary-based mutator

Kostya Serebryany via llvm-commits llvm-commits at lists.llvm.org
Wed Jan 6 17:49:36 PST 2016


Author: kcc
Date: Wed Jan  6 19:49:35 2016
New Revision: 257013

URL: http://llvm.org/viewvc/llvm-project?rev=257013&view=rev
Log:
[libFuzzer] add a position hint to the dictionary-based mutator

Added:
    llvm/trunk/lib/Fuzzer/test/fuzzer-dict.test
Modified:
    llvm/trunk/lib/Fuzzer/FuzzerDriver.cpp
    llvm/trunk/lib/Fuzzer/FuzzerInterface.h
    llvm/trunk/lib/Fuzzer/FuzzerMutate.cpp
    llvm/trunk/lib/Fuzzer/test/FuzzerUnittest.cpp
    llvm/trunk/lib/Fuzzer/test/fuzzer.test

Modified: llvm/trunk/lib/Fuzzer/FuzzerDriver.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/FuzzerDriver.cpp?rev=257013&r1=257012&r2=257013&view=diff
==============================================================================
--- llvm/trunk/lib/Fuzzer/FuzzerDriver.cpp (original)
+++ llvm/trunk/lib/Fuzzer/FuzzerDriver.cpp Wed Jan  6 19:49:35 2016
@@ -286,7 +286,7 @@ int FuzzerDriver(const std::vector<std::
   Fuzzer F(USF, Options);
 
   for (auto &U: Dictionary)
-    USF.GetMD().AddWordToDictionary(U.data(), U.size());
+    USF.GetMD().AddWordToManualDictionary(U);
 
   // Timer
   if (Flags.timeout > 0)

Modified: llvm/trunk/lib/Fuzzer/FuzzerInterface.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/FuzzerInterface.h?rev=257013&r1=257012&r2=257013&view=diff
==============================================================================
--- llvm/trunk/lib/Fuzzer/FuzzerInterface.h (original)
+++ llvm/trunk/lib/Fuzzer/FuzzerInterface.h Wed Jan  6 19:49:35 2016
@@ -16,6 +16,7 @@
 #ifndef LLVM_FUZZER_INTERFACE_H
 #define LLVM_FUZZER_INTERFACE_H
 
+#include <limits>
 #include <cstddef>
 #include <cstdint>
 #include <vector>
@@ -86,9 +87,13 @@ class MutationDispatcher {
   /// Mutates data by chanding one bit.
   size_t Mutate_ChangeBit(uint8_t *Data, size_t Size, size_t MaxSize);
 
-  /// Mutates data by adding a word from the dictionary.
-  size_t Mutate_AddWordFromDictionary(uint8_t *Data, size_t Size,
-                                      size_t MaxSize);
+  /// Mutates data by adding a word from the manual dictionary.
+  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);
 
   /// 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);
@@ -104,7 +109,8 @@ class MutationDispatcher {
   size_t CrossOver(const uint8_t *Data1, size_t Size1, const uint8_t *Data2,
                    size_t Size2, uint8_t *Out, size_t MaxOutSize);
 
-  void AddWordToDictionary(const uint8_t *Word, size_t Size);
+  void AddWordToManualDictionary(const Unit &Word);
+  void AddWordToAutoDictionary(const Unit &Word, size_t PositionHint);
   void SetCorpus(const std::vector<Unit> *Corpus);
 
  private:

Modified: llvm/trunk/lib/Fuzzer/FuzzerMutate.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/FuzzerMutate.cpp?rev=257013&r1=257012&r2=257013&view=diff
==============================================================================
--- llvm/trunk/lib/Fuzzer/FuzzerMutate.cpp (original)
+++ llvm/trunk/lib/Fuzzer/FuzzerMutate.cpp Wed Jan  6 19:49:35 2016
@@ -22,14 +22,21 @@ struct Mutator {
   const char *Name;
 };
 
+struct DictionaryEntry {
+  Unit Word;
+  size_t PositionHint;
+};
+
 struct MutationDispatcher::Impl {
-  std::vector<Unit> Dictionary;
+  std::vector<DictionaryEntry> ManualDictionary;
+  std::vector<DictionaryEntry> AutoDictionary;
   std::vector<Mutator> Mutators;
   std::vector<Mutator> CurrentMutatorSequence;
   const std::vector<Unit> *Corpus = nullptr;
+  FuzzerRandomBase &Rand;
 
   void Add(Mutator M) { Mutators.push_back(M); }
-  Impl() {
+  Impl(FuzzerRandomBase &Rand) : Rand(Rand) {
     Add({&MutationDispatcher::Mutate_EraseByte, "EraseByte"});
     Add({&MutationDispatcher::Mutate_InsertByte, "InsertByte"});
     Add({&MutationDispatcher::Mutate_ChangeByte, "ChangeByte"});
@@ -37,14 +44,14 @@ struct MutationDispatcher::Impl {
     Add({&MutationDispatcher::Mutate_ShuffleBytes, "ShuffleBytes"});
     Add({&MutationDispatcher::Mutate_ChangeASCIIInteger, "ChangeASCIIInt"});
     Add({&MutationDispatcher::Mutate_CrossOver, "CrossOver"});
-  }
-  void AddWordToDictionary(const uint8_t *Word, size_t Size) {
-    if (Dictionary.empty()) {
-      Add({&MutationDispatcher::Mutate_AddWordFromDictionary, "AddFromDict"});
-    }
-    Dictionary.push_back(Unit(Word, Word + Size));
+    Add({&MutationDispatcher::Mutate_AddWordFromManualDictionary,
+         "AddFromManualDict"});
+    Add({&MutationDispatcher::Mutate_AddWordFromAutoDictionary,
+         "AddFromAutoDict"});
   }
   void SetCorpus(const std::vector<Unit> *Corpus) { this->Corpus = Corpus; }
+  size_t AddWordFromDictionary(const std::vector<DictionaryEntry> &D,
+                               uint8_t *Data, size_t Size, size_t MaxSize);
 };
 
 static char FlipRandomBit(char X, FuzzerRandomBase &Rand) {
@@ -68,7 +75,8 @@ static char RandCh(FuzzerRandomBase &Ran
 size_t MutationDispatcher::Mutate_ShuffleBytes(uint8_t *Data, size_t Size,
                                                size_t MaxSize) {
   assert(Size);
-  size_t ShuffleAmount = Rand(std::min(Size, (size_t)8)) + 1;  // [1,8] and <= Size.
+  size_t ShuffleAmount =
+      Rand(std::min(Size, (size_t)8)) + 1; // [1,8] and <= Size.
   size_t ShuffleStart = Rand(Size - ShuffleAmount);
   assert(ShuffleStart + ShuffleAmount <= Size);
   std::random_shuffle(Data + ShuffleStart, Data + ShuffleStart + ShuffleAmount,
@@ -110,22 +118,38 @@ size_t MutationDispatcher::Mutate_Change
   return Size;
 }
 
-size_t MutationDispatcher::Mutate_AddWordFromDictionary(uint8_t *Data,
-                                                        size_t Size,
-                                                        size_t MaxSize) {
-  auto &D = MDImpl->Dictionary;
-  assert(!D.empty());
+size_t MutationDispatcher::Mutate_AddWordFromManualDictionary(uint8_t *Data,
+                                                              size_t Size,
+                                                              size_t MaxSize) {
+  return MDImpl->AddWordFromDictionary(MDImpl->ManualDictionary, Data, Size,
+                                       MaxSize);
+}
+
+size_t MutationDispatcher::Mutate_AddWordFromAutoDictionary(uint8_t *Data,
+                                                            size_t Size,
+                                                            size_t MaxSize) {
+  return MDImpl->AddWordFromDictionary(MDImpl->AutoDictionary, Data, Size,
+                                       MaxSize);
+}
+
+size_t MutationDispatcher::Impl::AddWordFromDictionary(
+    const std::vector<DictionaryEntry> &D, uint8_t *Data, size_t Size,
+    size_t MaxSize) {
   if (D.empty()) return 0;
-  const Unit &Word = D[Rand(D.size())];
+  const DictionaryEntry &DE = D[Rand(D.size())];
+  const Unit &Word = DE.Word;
+  size_t PositionHint = DE.PositionHint;
+  bool UsePositionHint = PositionHint != std::numeric_limits<size_t>::max() &&
+                         PositionHint + Word.size() < Size && Rand.RandBool();
   if (Rand.RandBool()) {  // Insert Word.
     if (Size + Word.size() > MaxSize) return 0;
-    size_t Idx = Rand(Size + 1);
+    size_t Idx = UsePositionHint ? PositionHint : Rand(Size + 1);
     memmove(Data + Idx + Word.size(), Data + Idx, Size - Idx);
     memcpy(Data + Idx, Word.data(), Word.size());
     return Size + Word.size();
   } else {  // Overwrite some bytes with Word.
     if (Word.size() > Size) return 0;
-    size_t Idx = Rand(Size - Word.size());
+    size_t Idx = UsePositionHint ? PositionHint : Rand(Size - Word.size());
     memcpy(Data + Idx, Word.data(), Word.size());
     return Size;
   }
@@ -219,12 +243,18 @@ void MutationDispatcher::SetCorpus(const
   MDImpl->SetCorpus(Corpus);
 }
 
-void MutationDispatcher::AddWordToDictionary(const uint8_t *Word, size_t Size) {
-  MDImpl->AddWordToDictionary(Word, Size);
+void MutationDispatcher::AddWordToManualDictionary(const Unit &Word) {
+  MDImpl->ManualDictionary.push_back(
+      {Word, std::numeric_limits<size_t>::max()});
+}
+
+void MutationDispatcher::AddWordToAutoDictionary(const Unit &Word,
+                                                 size_t PositionHint) {
+  MDImpl->AutoDictionary.push_back({Word, PositionHint});
 }
 
 MutationDispatcher::MutationDispatcher(FuzzerRandomBase &Rand) : Rand(Rand) {
-  MDImpl = new Impl;
+  MDImpl = new Impl(Rand);
 }
 
 MutationDispatcher::~MutationDispatcher() { delete MDImpl; }

Modified: llvm/trunk/lib/Fuzzer/test/FuzzerUnittest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/test/FuzzerUnittest.cpp?rev=257013&r1=257012&r2=257013&view=diff
==============================================================================
--- llvm/trunk/lib/Fuzzer/test/FuzzerUnittest.cpp (original)
+++ llvm/trunk/lib/Fuzzer/test/FuzzerUnittest.cpp Wed Jan  6 19:49:35 2016
@@ -247,8 +247,8 @@ void TestAddWordFromDictionary(Mutator M
   MutationDispatcher MD(Rand);
   uint8_t Word1[4] = {0xAA, 0xBB, 0xCC, 0xDD};
   uint8_t Word2[3] = {0xFF, 0xEE, 0xEF};
-  MD.AddWordToDictionary(Word1, sizeof(Word1));
-  MD.AddWordToDictionary(Word2, sizeof(Word2));
+  MD.AddWordToManualDictionary(Unit(Word1, Word1 + sizeof(Word1)));
+  MD.AddWordToManualDictionary(Unit(Word2, Word2 + sizeof(Word2)));
   int FoundMask = 0;
   uint8_t CH0[7] = {0x00, 0x11, 0x22, 0xAA, 0xBB, 0xCC, 0xDD};
   uint8_t CH1[7] = {0x00, 0x11, 0xAA, 0xBB, 0xCC, 0xDD, 0x22};
@@ -274,14 +274,41 @@ void TestAddWordFromDictionary(Mutator M
 }
 
 TEST(FuzzerMutate, AddWordFromDictionary1) {
-  TestAddWordFromDictionary(&MutationDispatcher::Mutate_AddWordFromDictionary,
-                            1 << 15);
+  TestAddWordFromDictionary(
+      &MutationDispatcher::Mutate_AddWordFromManualDictionary, 1 << 15);
 }
 
 TEST(FuzzerMutate, AddWordFromDictionary2) {
   TestAddWordFromDictionary(&MutationDispatcher::Mutate, 1 << 15);
 }
 
+void TestAddWordFromDictionaryWithHint(Mutator M, int NumIter) {
+  FuzzerRandomLibc Rand(0);
+  MutationDispatcher MD(Rand);
+  uint8_t Word[] = {0xAA, 0xBB, 0xCC, 0xDD, 0xFF, 0xEE, 0xEF};
+  size_t PosHint = 7777;
+  MD.AddWordToAutoDictionary(Unit(Word, Word + sizeof(Word)), PosHint);
+  int FoundMask = 0;
+  for (int i = 0; i < NumIter; i++) {
+    uint8_t T[10000];
+    memset(T, 0, sizeof(T));
+    size_t NewSize = (MD.*M)(T, 9000, 10000);
+    if (NewSize >= PosHint + sizeof(Word) &&
+        !memcmp(Word, T + PosHint, sizeof(Word)))
+      FoundMask = 1;
+  }
+  EXPECT_EQ(FoundMask, 1);
+}
+
+TEST(FuzzerMutate, AddWordFromDictionaryWithHint1) {
+  TestAddWordFromDictionaryWithHint(
+      &MutationDispatcher::Mutate_AddWordFromAutoDictionary, 1 << 5);
+}
+
+TEST(FuzzerMutate, AddWordFromDictionaryWithHint2) {
+  TestAddWordFromDictionaryWithHint(&MutationDispatcher::Mutate, 1 << 10);
+}
+
 void TestChangeASCIIInteger(Mutator M, int NumIter) {
   FuzzerRandomLibc Rand(0);
   MutationDispatcher MD(Rand);

Added: llvm/trunk/lib/Fuzzer/test/fuzzer-dict.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/test/fuzzer-dict.test?rev=257013&view=auto
==============================================================================
--- llvm/trunk/lib/Fuzzer/test/fuzzer-dict.test (added)
+++ llvm/trunk/lib/Fuzzer/test/fuzzer-dict.test Wed Jan  6 19:49:35 2016
@@ -0,0 +1,6 @@
+CHECK: BINGO
+Done1000000: Done 1000000 runs in
+
+RUN: not LLVMFuzzer-SimpleDictionaryTest -dict=%S/dict1.txt -seed=1 -runs=1000003  2>&1 | FileCheck %s
+RUN:     LLVMFuzzer-SimpleDictionaryTest                    -seed=1 -runs=1000000  2>&1 | FileCheck %s --check-prefix=Done1000000
+

Modified: llvm/trunk/lib/Fuzzer/test/fuzzer.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/test/fuzzer.test?rev=257013&r1=257012&r2=257013&view=diff
==============================================================================
--- llvm/trunk/lib/Fuzzer/test/fuzzer.test (original)
+++ llvm/trunk/lib/Fuzzer/test/fuzzer.test Wed Jan  6 19:49:35 2016
@@ -20,14 +20,12 @@ NullDerefTestExactPath: Test unit writte
 RUN: not LLVMFuzzer-CounterTest -use_counters=1 -max_len=6 -seed=1 -timeout=15 2>&1 | FileCheck %s
 
 RUN: not LLVMFuzzer-CallerCalleeTest                     -cross_over=0 -max_len=6 -seed=1 -timeout=15 2>&1 | FileCheck %s
-RUN:     LLVMFuzzer-CallerCalleeTest  -use_indir_calls=0 -cross_over=0 -max_len=6 -seed=1 -runs=1000000 2>&1 | FileCheck %s  --check-prefix=Done1000000
+# This one is flaky, may actually find the goal even w/o use_indir_calls.
+# LLVMFuzzer-CallerCalleeTest  -use_indir_calls=0 -cross_over=0 -max_len=6 -seed=1 -runs=1000000 2>&1 | FileCheck %s  --check-prefix=Done1000000
 
 
 RUN: not LLVMFuzzer-UserSuppliedFuzzerTest -seed=1 -timeout=15 2>&1 | FileCheck %s
 
-RUN: not LLVMFuzzer-SimpleDictionaryTest -dict=%S/dict1.txt -seed=1 -runs=1000003  2>&1 | FileCheck %s
-RUN:     LLVMFuzzer-SimpleDictionaryTest                    -seed=1 -runs=1000000  2>&1 | FileCheck %s --check-prefix=Done1000000
-
 RUN: not LLVMFuzzer-UninstrumentedTest-Uninstrumented 2>&1 | FileCheck %s --check-prefix=UNINSTRUMENTED
 UNINSTRUMENTED: ERROR: __sanitizer_set_death_callback is not defined. Exiting.
 




More information about the llvm-commits mailing list