[libFuzzer] start refactoring the Mutator and adding tests to it
authorKostya Serebryany <kcc@google.com>
Sat, 1 Aug 2015 01:42:51 +0000 (01:42 +0000)
committerKostya Serebryany <kcc@google.com>
Sat, 1 Aug 2015 01:42:51 +0000 (01:42 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@243817 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Fuzzer/FuzzerInternal.h
lib/Fuzzer/FuzzerMutate.cpp
lib/Fuzzer/FuzzerTraceState.cpp
lib/Fuzzer/test/FuzzerUnittest.cpp
lib/Fuzzer/test/fuzzer-dfsan.test

index fe7869871f058482b8ed9aed6b0798070aa53e36..274fdf077a7fb7582a066873a23db3bfc274857e 100644 (file)
@@ -33,6 +33,8 @@ void CopyFileToErr(const std::string &Path);
 std::string DirPlusFile(const std::string &DirPath,
                         const std::string &FileName);
 
+size_t Mutate_EraseByte(uint8_t *Data, size_t size, size_t MaxSize,
+                        FuzzerRandomBase &Rand);
 size_t Mutate(uint8_t *Data, size_t Size, size_t MaxSize,
               FuzzerRandomBase &Rand);
 
index 66df98a66f5da71cfec7450097a0d978cea3e4b3..eec6475f9b8464cee515afa0b4af14a2f51e4dd5 100644 (file)
@@ -33,6 +33,16 @@ static char RandCh(FuzzerRandomBase &Rand) {
   return Special[Rand(sizeof(Special) - 1)];
 }
 
+size_t Mutate_EraseByte(uint8_t *Data, size_t Size, size_t MaxSize,
+                        FuzzerRandomBase &Rand) {
+  assert(Size);
+  if (Size == 1) return Size;
+  size_t Idx = Rand(Size);
+  // Erase Data[Idx].
+  memmove(Data + Idx, Data + Idx + 1, Size - Idx - 1);
+  return Size - 1;
+}
+
 // Mutates Data in place, returns new size.
 size_t Mutate(uint8_t *Data, size_t Size, size_t MaxSize,
               FuzzerRandomBase &Rand) {
@@ -46,13 +56,7 @@ size_t Mutate(uint8_t *Data, size_t Size, size_t MaxSize,
   assert(Size > 0);
   size_t Idx = Rand(Size);
   switch (Rand(3)) {
-  case 0:
-    if (Size > 1) {
-      // Erase Data[Idx].
-      memmove(Data + Idx, Data + Idx + 1, Size - Idx - 1);
-      Size = Size - 1;
-    }
-    [[clang::fallthrough]];
+  case 0: Size = Mutate_EraseByte(Data, Size, MaxSize, Rand); break;
   case 1:
     if (Size < MaxSize) {
       // Insert new value at Data[Idx].
index f0537c005800bb3476789eb0a22f67c67ecdbcb0..1c01e8aa77baee95d22e88af5629e7860fbc634d 100644 (file)
@@ -140,7 +140,7 @@ static bool ComputeCmp(size_t CmpSize, size_t CmpType, uint64_t Arg1,
   if (CmpSize == 1) return ComputeCmp<uint8_t, int8_t>(CmpType, Arg1, Arg2);
   // Other size, ==
   if (CmpType == ICMP_EQ) return Arg1 == Arg2;
-  assert(0 && "unsupported cmp and type size combination");
+  // assert(0 && "unsupported cmp and type size combination");
   return true;
 }
 
index ed52a55a507d6cfb6d0eac70cc32467032531f86..a159e41140442915c02d0a5d71913f20eaddd734 100644 (file)
@@ -2,6 +2,8 @@
 #include "gtest/gtest.h"
 #include <set>
 
+using namespace fuzzer;
+
 // For now, have LLVMFuzzerTestOneInput just to make it link.
 // Later we may want to make unittests that actually call LLVMFuzzerTestOneInput.
 extern "C" void LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
@@ -9,7 +11,6 @@ extern "C" void LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
 }
 
 TEST(Fuzzer, CrossOver) {
-  using namespace fuzzer;
   FuzzerRandomLibc Rand(0);
   Unit A({0, 1, 2}), B({5, 6, 7});
   Unit C;
@@ -72,3 +73,36 @@ TEST(Fuzzer, Hash) {
   U.push_back('d');
   EXPECT_EQ("81fe8bfe87576c3ecb22426f8e57847382917acf", fuzzer::Hash(U));
 }
+
+typedef size_t (*Mutator)(uint8_t *Data, size_t Size, size_t MaxSize,
+                          FuzzerRandomBase &Rand);
+
+void TestEraseByte(Mutator M, int NumIter) {
+  uint8_t REM0[8] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77};
+  uint8_t REM1[8] = {0x00, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77};
+  uint8_t REM2[8] = {0x00, 0x11, 0x33, 0x44, 0x55, 0x66, 0x77};
+  uint8_t REM3[8] = {0x00, 0x11, 0x22, 0x44, 0x55, 0x66, 0x77};
+  uint8_t REM4[8] = {0x00, 0x11, 0x22, 0x33, 0x55, 0x66, 0x77};
+  uint8_t REM5[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x66, 0x77};
+  uint8_t REM6[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x77};
+  uint8_t REM7[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66};
+  FuzzerRandomLibc Rand(0);
+  int FoundMask = 0;
+  for (int i = 0; i < NumIter; i++) {
+    uint8_t T[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77};
+    size_t NewSize = Mutate_EraseByte(T, sizeof(T), sizeof(T), Rand);
+    EXPECT_EQ(7UL, NewSize);
+    if (!memcmp(REM0, T, 7)) FoundMask |= 1 << 0;
+    if (!memcmp(REM1, T, 7)) FoundMask |= 1 << 1;
+    if (!memcmp(REM2, T, 7)) FoundMask |= 1 << 2;
+    if (!memcmp(REM3, T, 7)) FoundMask |= 1 << 3;
+    if (!memcmp(REM4, T, 7)) FoundMask |= 1 << 4;
+    if (!memcmp(REM5, T, 7)) FoundMask |= 1 << 5;
+    if (!memcmp(REM6, T, 7)) FoundMask |= 1 << 6;
+    if (!memcmp(REM7, T, 7)) FoundMask |= 1 << 7;
+  }
+  EXPECT_EQ(FoundMask, 255);
+}
+
+TEST(FuzzerMutate, EraseByte1) { TestEraseByte(Mutate_EraseByte, 50); }
+TEST(FuzzerMutate, EraseByte2) { TestEraseByte(Mutate, 100); }
index c9d00f1d95058ca0b95263d1619fe34270734d2c..266cb51a594397862cfb2a1dd4291d9270afbef9 100644 (file)
@@ -1,15 +1,19 @@
-CHECK: BINGO
+CHECK1: BINGO
+CHECK2: BINGO
+CHECK3: BINGO
+CHECK4: BINGO
+
 CHECK_DFSanCmpCallback: DFSanCmpCallback: PC
 CHECK_DFSanSwitchCallback: DFSanSwitchCallback: PC
 
-RUN: not LLVMFuzzer-SimpleCmpTest-DFSan -use_traces=1 -seed=1 -runs=1000000 -timeout=5 2>&1 | FileCheck %s
+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=1000 -timeout=5 2>&1 | FileCheck %s
+RUN: not LLVMFuzzer-MemcmpTest-DFSan -use_traces=1 -seed=1 -runs=1000 -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_DFSanCmpCallback
 
-RUN: not LLVMFuzzer-StrncmpTest-DFSan -use_traces=1 -seed=1 -runs=10000 -timeout=5 2>&1 | FileCheck %s
+RUN: not LLVMFuzzer-StrncmpTest-DFSan -use_traces=1 -seed=1 -runs=10000 -timeout=5 2>&1 | FileCheck %s --check-prefix=CHECK3
 RUN: LLVMFuzzer-StrncmpTest-DFSan -use_traces=1 -seed=1 -runs=2 -timeout=5 -verbosity=3 2>&1 | FileCheck %s  -check-prefix=CHECK_DFSanCmpCallback
 
-RUN: not LLVMFuzzer-SwitchTest-DFSan -use_traces=1 -seed=1 -runs=10000 -timeout=5              2>&1 | FileCheck %s
+RUN: not LLVMFuzzer-SwitchTest-DFSan -use_traces=1 -seed=1 -runs=100000 -timeout=5              2>&1 | FileCheck %s --check-prefix=CHECK4
 RUN:     LLVMFuzzer-SwitchTest-DFSan -use_traces=1 -seed=1 -runs=2     -timeout=5 -verbosity=3 2>&1 | FileCheck %s  -check-prefix=CHECK_DFSanSwitchCallback