]> granicus.if.org Git - llvm/commitdiff
[libFuzzer] change trace-pc to use 8-byte guards
authorKostya Serebryany <kcc@google.com>
Sat, 17 Sep 2016 05:04:47 +0000 (05:04 +0000)
committerKostya Serebryany <kcc@google.com>
Sat, 17 Sep 2016 05:04:47 +0000 (05:04 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@281810 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Fuzzer/FuzzerInternal.h
lib/Fuzzer/FuzzerLoop.cpp
lib/Fuzzer/FuzzerTracePC.cpp
lib/Fuzzer/test/DSO1.cpp [new file with mode: 0644]
lib/Fuzzer/test/DSO2.cpp [new file with mode: 0644]
lib/Fuzzer/test/DSOTestExtra.cpp [new file with mode: 0644]
lib/Fuzzer/test/DSOTestMain.cpp [new file with mode: 0644]
lib/Fuzzer/test/fuzzer-jobs.test
lib/Fuzzer/test/fuzzer.test
lib/Fuzzer/test/trace-pc/CMakeLists.txt

index 1ee1b8f718f487abbc6bc7ba1e34e092638fde83..69b38abc26f25eebad533b704c7837c3b68b95a4 100644 (file)
@@ -358,8 +358,8 @@ private:
 // See TracePC.cpp
 class TracePC {
  public:
-  void HandleTrace(uint8_t *guard, uintptr_t PC);
-  void HandleInit(uint8_t *start, uint8_t *stop);
+  void HandleTrace(uint64_t *guard, uintptr_t PC);
+  void HandleInit(uint64_t *start, uint64_t *stop);
   void HandleCallerCallee(uintptr_t Caller, uintptr_t Callee);
   size_t GetTotalCoverage() { return TotalCoverage; }
   void SetUseCounters(bool UC) { UseCounters = UC; }
@@ -374,6 +374,16 @@ class TracePC {
     return Res;
   }
 
+  void Reset() {
+    TotalCoverage = 0;
+    TotalCounterBits = 0;
+    NumNewPCs = 0;
+    CounterMap.Reset();
+    TotalCoverageMap.Reset();
+  }
+
+  void PrintModuleInfo();
+
 private:
   bool UseCounters = false;
   size_t TotalCoverage = 0;
@@ -384,7 +394,14 @@ private:
   size_t NumNewPCs = 0;
   void AddNewPC(uintptr_t PC) { NewPCs[(NumNewPCs++) % kMaxNewPCs] = PC; }
 
-  uint8_t *Start, *Stop;
+  struct Module {
+    uint64_t *Start, *Stop;
+  };
+
+  Module Modules[4096];
+  size_t NumModules = 0;
+  size_t NumGuards = 0;
+
   ValueBitMap CounterMap;
   ValueBitMap TotalCoverageMap;
 };
index 7cb1d4906a513076dadbe5a526ddffd9b5c037f3..348e7573773490632245c899ace51c6d4281fad1 100644 (file)
@@ -170,6 +170,8 @@ Fuzzer::Fuzzer(UserCallback CB, MutationDispatcher &MD, FuzzingOptions Options)
     PcBuffer = new uintptr_t[PcBufferLen];
     EF->__sanitizer_set_coverage_pc_buffer(PcBuffer, PcBufferLen);
   }
+  if (Options.Verbosity)
+    TPC.PrintModuleInfo();
 }
 
 Fuzzer::~Fuzzer() { }
@@ -735,6 +737,7 @@ size_t Fuzzer::ChooseUnitIdxToMutate() {
 void Fuzzer::ResetCoverage() {
   ResetEdgeCoverage();
   MaxCoverage.Reset();
+  TPC.Reset();
   PrepareCounters(&MaxCoverage);
 }
 
index f729a5e687871a65cbb656631e3d5c50d3cd903e..8fa9257c23b2c0f1859384e10beaa6fb77eaa833 100644 (file)
@@ -18,49 +18,67 @@ namespace fuzzer {
 
 TracePC TPC;
 
-void TracePC::HandleTrace(uint8_t *Guard, uintptr_t PC) {
+void TracePC::HandleTrace(uint64_t *Guard, uintptr_t PC) {
+  const uint64_t kBit63 = 1ULL << 63;
+  uint64_t Value = *Guard;
+  if (Value & kBit63) return;
+  // Printf("   >> %16zx %p\n", Value, Guard);
   if (UseCounters) {
-    uintptr_t GV = *Guard;
-    if (GV == 0) {
-      size_t Idx = Guard - Start;
+    uint64_t Counter = Value & 0xff;
+    if (Counter == 0) {
+      size_t Idx = Value >> 32;
       if (TotalCoverageMap.AddValue(Idx)) {
         TotalCoverage++;
         AddNewPC(PC);
       }
     }
-    if (GV < 255)
-      GV++;
-    *Guard = GV;
+    if (Counter < 255)
+      Value++;
   } else {
-    *Guard = 0xff;
+    Value |= kBit63;
     TotalCoverage++;
     AddNewPC(PC);
   }
+  // Printf("   << %16zx\n", Value);
+  *Guard = Value;
 }
 
-void TracePC::HandleInit(uint8_t *Start, uint8_t *Stop) {
-  // TODO: this handles only one DSO/binary.
-  this->Start = Start;
-  this->Stop = Stop;
+void TracePC::HandleInit(uint64_t *Start, uint64_t *Stop) {
+  if (Start == Stop || *Start) return;
+  assert(NumModules < sizeof(Modules) / sizeof(Modules[0]));
+  for (uint64_t *P = Start; P < Stop; P++)
+    *P = (++NumGuards) << 32;
+  Modules[NumModules].Start = Start;
+  Modules[NumModules].Stop = Stop;
+  NumModules++;
+}
+
+void TracePC::PrintModuleInfo() {
+  Printf("INFO: Loaded %zd modules (%zd guards): ", NumModules, NumGuards);
+  for (size_t i = 0; i < NumModules; i++)
+    Printf("[%p, %p), ", Modules[i].Start, Modules[i].Stop);
+  Printf("\n");
 }
 
 void TracePC::FinalizeTrace() {
   if (UseCounters && TotalCoverage) {
-    for (uint8_t *X = Start; X < Stop; X++) {
-      uint8_t Value = *X;
-      size_t Idx = X - Start;
-      if (Value >= 1) {
-        unsigned Bit = 0;
-        /**/ if (Value >= 128) Bit = 7;
-        else if (Value >= 32) Bit = 6;
-        else if (Value >= 16) Bit = 5;
-        else if (Value >= 8) Bit = 4;
-        else if (Value >= 4) Bit = 3;
-        else if (Value >= 3) Bit = 2;
-        else if (Value >= 2) Bit = 1;
-        CounterMap.AddValue(Idx * 8 + Bit);
+    for (size_t M = 0; M < NumModules; M++) {
+      for (uint64_t *X = Modules[M].Start; X < Modules[M].Stop; X++) {
+        uint64_t Value = *X & 0xff;
+        uint64_t Idx = *X >> 32;
+        if (Value >= 1) {
+          unsigned Bit = 0;
+          /**/ if (Value >= 128) Bit = 7;
+          else if (Value >= 32) Bit = 6;
+          else if (Value >= 16) Bit = 5;
+          else if (Value >= 8) Bit = 4;
+          else if (Value >= 4) Bit = 3;
+          else if (Value >= 3) Bit = 2;
+          else if (Value >= 2) Bit = 1;
+          CounterMap.AddValue(Idx * 8 + Bit);
+        }
+        *X = Idx << 32;
       }
-      *X = 0;
     }
   }
 }
@@ -83,13 +101,13 @@ void TracePC::HandleCallerCallee(uintptr_t Caller, uintptr_t Callee) {
 
 extern "C" {
 __attribute__((visibility("default")))
-void __sanitizer_cov_trace_pc_guard(uint8_t *Guard) {
+void __sanitizer_cov_trace_pc_guard(uint64_t *Guard) {
   uintptr_t PC = (uintptr_t)__builtin_return_address(0);
   fuzzer::TPC.HandleTrace(Guard, PC);
 }
 
 __attribute__((visibility("default")))
-void __sanitizer_cov_trace_pc_guard_init(uint8_t *Start, uint8_t *Stop) {
+void __sanitizer_cov_trace_pc_guard_init(uint64_t *Start, uint64_t *Stop) {
   fuzzer::TPC.HandleInit(Start, Stop);
 }
 
diff --git a/lib/Fuzzer/test/DSO1.cpp b/lib/Fuzzer/test/DSO1.cpp
new file mode 100644 (file)
index 0000000..c362593
--- /dev/null
@@ -0,0 +1,11 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Source code for a simple DSO.
+
+int DSO1(int a) {
+  if (a < 123456)
+    return 0;
+  return 1;
+}
+
diff --git a/lib/Fuzzer/test/DSO2.cpp b/lib/Fuzzer/test/DSO2.cpp
new file mode 100644 (file)
index 0000000..46c80e4
--- /dev/null
@@ -0,0 +1,11 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Source code for a simple DSO.
+
+int DSO2(int a) {
+  if (a < 3598235)
+    return 0;
+  return 1;
+}
+
diff --git a/lib/Fuzzer/test/DSOTestExtra.cpp b/lib/Fuzzer/test/DSOTestExtra.cpp
new file mode 100644 (file)
index 0000000..a2274d0
--- /dev/null
@@ -0,0 +1,11 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Source code for a simple DSO.
+
+int DSOTestExtra(int a) {
+  if (a < 452345)
+    return 0;
+  return 1;
+}
+
diff --git a/lib/Fuzzer/test/DSOTestMain.cpp b/lib/Fuzzer/test/DSOTestMain.cpp
new file mode 100644 (file)
index 0000000..49cd185
--- /dev/null
@@ -0,0 +1,27 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Source code for a simple DSO.
+
+#include <cstdint>
+#include <cstdlib>
+#include <cstring>
+#include <cstdio>
+extern int DSO1(int a);
+extern int DSO2(int a);
+extern int DSOTestExtra(int a);
+
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+  if (Size < sizeof(int) * 3) return 0;
+  int x, y, z;
+  memcpy(&x, Data + 0 * sizeof(int), sizeof(int));
+  memcpy(&y, Data + 1 * sizeof(int), sizeof(int));
+  memcpy(&z, Data + 2 * sizeof(int), sizeof(int));
+  int sum = DSO1(x) + DSO2(y) + DSOTestExtra(z);
+  if (sum == 3) {
+    fprintf(stderr, "BINGO %d %d %d\n", x, y, z);
+    exit(1);
+  }
+  return 0;
+}
index cd71bc07972e020950502639d03380fdd70bb3a9..5bf8cfadfb75a6d7c1b154a433a19602778e44f6 100644 (file)
@@ -9,7 +9,7 @@ RUN: rm -f fuzz-{0,1}.log
 RUN: LLVMFuzzer-EmptyTest -max_total_time=4 -jobs=2 -workers=2 FuzzerJobsTestCORPUS > %t-fuzzer-jobs-test.log 2>&1 & export FUZZER_PID=$!
 # Wait a short while to give time for the child processes
 # to start fuzzing
-RUN: sleep 1
+RUN: sleep 2
 # If the instances are running in parallel they should have created their log
 # files by now.
 RUN: ls fuzz-0.log
index 0e7b26ec7260b312f5b4a794455ff0b85c20387e..ce207855e52e4c173b02e57ce4cbc5c03724ae02 100644 (file)
@@ -49,3 +49,7 @@ OOB: is located 0 bytes to the right of 3-byte region
 
 RUN: not LLVMFuzzer-InitializeTest 2>&1 | FileCheck %s
 
+RUN: not LLVMFuzzer-DSOTest 2>&1 | FileCheck %s --check-prefix=DSO
+DSO: INFO: Loaded 3 modules
+DSO: BINGO
+
index 4ecf80163a0dec1515d1d9814eddfe327174b969..c4e4e9c29d4d51c7fe0a11ce51d0c71830c4938c 100644 (file)
@@ -15,3 +15,25 @@ endforeach()
 
 # Propagate value into parent directory
 set(TestBinaries ${TestBinaries} PARENT_SCOPE)
+
+add_library(LLVMFuzzer-DSO1 SHARED ../DSO1.cpp)
+add_library(LLVMFuzzer-DSO2 SHARED ../DSO2.cpp)
+
+add_executable(LLVMFuzzer-DSOTest
+  ../DSOTestMain.cpp
+  ../DSOTestExtra.cpp)
+
+target_link_libraries(LLVMFuzzer-DSOTest
+  LLVMFuzzer-DSO1
+  LLVMFuzzer-DSO2
+  LLVMFuzzer
+  )
+
+set_target_properties(LLVMFuzzer-DSOTest PROPERTIES RUNTIME_OUTPUT_DIRECTORY
+  "${CMAKE_BINARY_DIR}/lib/Fuzzer/test")
+set_target_properties(LLVMFuzzer-DSO1 PROPERTIES LIBRARY_OUTPUT_DIRECTORY
+  "${CMAKE_BINARY_DIR}/lib/Fuzzer/lib")
+set_target_properties(LLVMFuzzer-DSO2 PROPERTIES LIBRARY_OUTPUT_DIRECTORY
+  "${CMAKE_BINARY_DIR}/lib/Fuzzer/lib")
+
+set(TestBinaries ${TestBinaries} LLVMFuzzer-DSOTest)