]> granicus.if.org Git - llvm/commitdiff
[libFuzzer] prototype implementation of recursion-depth coverage features (commented...
authorKostya Serebryany <kcc@google.com>
Thu, 20 Jul 2017 01:35:17 +0000 (01:35 +0000)
committerKostya Serebryany <kcc@google.com>
Thu, 20 Jul 2017 01:35:17 +0000 (01:35 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@308577 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Fuzzer/FuzzerLoop.cpp
lib/Fuzzer/FuzzerTracePC.cpp
lib/Fuzzer/FuzzerTracePC.h
lib/Fuzzer/FuzzerValueBitMap.h
lib/Fuzzer/test/DeepRecursionTest.cpp

index 8ac7a847aef75790b0645aa9c8960ee8446d1bcc..37adb1e0a5adee1cca3d9f0fe6b2e55855093624 100644 (file)
@@ -456,6 +456,7 @@ static bool LooseMemeq(const uint8_t *A, const uint8_t *B, size_t Size) {
 }
 
 void Fuzzer::ExecuteCallback(const uint8_t *Data, size_t Size) {
+  TPC.RecordInitialStack();
   TotalNumberOfRuns++;
   assert(InFuzzingThread());
   if (SMR.IsClient())
index ced0a213334081109cf7ff8acc0d61672a6baa84..07be441244c7088fe4489cda15820475fa1a294b 100644 (file)
@@ -319,6 +319,8 @@ void __sanitizer_cov_trace_pc_guard(uint32_t *Guard) {
   uint32_t Idx = *Guard;
   __sancov_trace_pc_pcs[Idx] = PC;
   __sancov_trace_pc_guard_8bit_counters[Idx]++;
+  // Uncomment the following line to get stack-depth profiling.
+  // fuzzer::TPC.RecordCurrentStack();
 }
 
 // Best-effort support for -fsanitize-coverage=trace-pc, which is available
index b36c4f54306cb6e92b07038370def0fa1d58e8d8..26e1d09e482c62023b223007e275ba747bf4bfba 100644 (file)
@@ -115,6 +115,20 @@ class TracePC {
     return PCs()[Idx];
   }
 
+  void RecordCurrentStack() {
+    uintptr_t Stack = GetCurrentStack();
+    if (Stack < LowestStack)
+      LowestStack = Stack;
+  }
+  void RecordInitialStack() {
+    InitialStack = GetCurrentStack();
+    LowestStack = InitialStack;
+  }
+  uintptr_t GetCurrentStack() const {
+    return reinterpret_cast<uintptr_t>(__builtin_frame_address(0));
+  }
+  uintptr_t GetMaxStackOffset() const { return InitialStack - LowestStack; }
+
 private:
   bool UseCounters = false;
   bool UseValueProfile = false;
@@ -138,6 +152,7 @@ private:
   std::set<uintptr_t> *PrintedPCs;
 
   ValueBitMap ValueProfileMap;
+  uintptr_t InitialStack, LowestStack;  // Assume stack grows down.
 };
 
 template <class Callback> // void Callback(size_t Idx, uint8_t Value);
@@ -196,11 +211,17 @@ void TracePC::CollectFeatures(Callback HandleFeature) const {
 
   ForEachNonZeroByte(ExtraCountersBegin(), ExtraCountersEnd(), FirstFeature,
                      Handle8bitCounter);
+  FirstFeature += (ExtraCountersEnd() - ExtraCountersBegin()) * 8;
 
-  if (UseValueProfile)
+  if (UseValueProfile) {
     ValueProfileMap.ForEach([&](size_t Idx) {
-      HandleFeature(N * 8 + Idx);
+      HandleFeature(FirstFeature + Idx);
     });
+    FirstFeature += ValueProfileMap.SizeInBits();
+  }
+
+  if (auto MaxStackOffset = GetMaxStackOffset())
+    HandleFeature(FirstFeature + MaxStackOffset);
 }
 
 extern TracePC TPC;
index 8f7ff74300f45c4c55d0de83196125a9be305844..f11de68252d97391cf45b1e19ab80861d191bb35 100644 (file)
@@ -52,6 +52,8 @@ struct ValueBitMap {
     return Map[WordIdx] & (1UL << BitIdx);
   }
 
+  size_t SizeInBits() const { return kMapSizeInBits; }
+
   size_t GetNumBitsSinceLastMerge() const { return NumBits; }
 
   // Merges 'Other' into 'this', clears 'Other', updates NumBits,
index 39a1602d7aca432815f66496ef1b0b994a031d93..bf4621d04923e6c06cb8f2c7125cf060b7d884eb 100644 (file)
@@ -3,7 +3,7 @@
 
 // Simple test for a fuzzer. The fuzzer must find the deep recursion.
 // To generate a crashy input:
-// for((i=0;i<100;i++)); do echo -n ABCDEFGHIJKLMNOPQRSTUVWXYZ  >> INPUT; done
+// for((i=0;i<110;i++)); do echo -n ABCDEFGHIJ  >> INPUT; done
 #include <cstddef>
 #include <cstdint>
 #include <cstdlib>
@@ -13,7 +13,7 @@ static volatile int Sink;
 void Recursive(const uint8_t *Data, size_t Size, int Depth) {
   if (Depth > 1000) abort();
   if (!Size) return;
-  if (*Data == ('A' + Depth % 26))
+  if (*Data == ('A' + Depth % 10))
     Recursive(Data + 1, Size - 1, Depth + 1);
   Sink++;
 }