[llvm] r270929 - [libFuzzer] more refactoring around CurrentUnit. Also add a threading test on which we currently have a race (when reporting bugs from multiple threads)

Kostya Serebryany via llvm-commits llvm-commits at lists.llvm.org
Thu May 26 15:17:35 PDT 2016


Author: kcc
Date: Thu May 26 17:17:32 2016
New Revision: 270929

URL: http://llvm.org/viewvc/llvm-project?rev=270929&view=rev
Log:
[libFuzzer] more refactoring around CurrentUnit. Also add a threading test on which we currently have a race (when reporting bugs from multiple threads)

Added:
    llvm/trunk/lib/Fuzzer/test/SimpleThreadedTest.cpp
Modified:
    llvm/trunk/lib/Fuzzer/FuzzerInternal.h
    llvm/trunk/lib/Fuzzer/FuzzerLoop.cpp
    llvm/trunk/lib/Fuzzer/test/CMakeLists.txt
    llvm/trunk/lib/Fuzzer/test/fuzzer-leak.test

Modified: llvm/trunk/lib/Fuzzer/FuzzerInternal.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/FuzzerInternal.h?rev=270929&r1=270928&r2=270929&view=diff
==============================================================================
--- llvm/trunk/lib/Fuzzer/FuzzerInternal.h (original)
+++ llvm/trunk/lib/Fuzzer/FuzzerInternal.h Thu May 26 17:17:32 2016
@@ -403,11 +403,7 @@ public:
   void ResetCoverage();
 
   bool InFuzzingThread() const { return IsMyThread; }
-  size_t GetCurrentUnitInFuzzingThead(const uint8_t **Data) const {
-    assert(InFuzzingThread());
-    *Data = CurrentUnitData;
-    return CurrentUnitSize;
-  }
+  size_t GetCurrentUnitInFuzzingThead(const uint8_t **Data) const;
 
 private:
   void AlarmCallback();
@@ -445,6 +441,8 @@ private:
   void DumpCurrentUnit(const char *Prefix);
   void DeathCallback();
 
+  void SetCurrentUnit(const uint8_t *Data, size_t Size);
+  size_t GetCurrentUnitNoThreadCheck(const uint8_t **Data) const;
   const uint8_t *CurrentUnitData = nullptr;
   size_t CurrentUnitSize = 0;
   bool InOOMState = false;

Modified: llvm/trunk/lib/Fuzzer/FuzzerLoop.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/FuzzerLoop.cpp?rev=270929&r1=270928&r2=270929&view=diff
==============================================================================
--- llvm/trunk/lib/Fuzzer/FuzzerLoop.cpp (original)
+++ llvm/trunk/lib/Fuzzer/FuzzerLoop.cpp Thu May 26 17:17:32 2016
@@ -170,20 +170,19 @@ void Fuzzer::StaticDeathCallback() {
 }
 
 void Fuzzer::DumpCurrentUnit(const char *Prefix) {
-  if (CurrentUnitSize <= kMaxUnitSizeToPrint) {
-    PrintHexArray(CurrentUnitData, CurrentUnitSize, "\n");
-    PrintASCII(CurrentUnitData, CurrentUnitSize, "\n");
+  const uint8_t *UnitData;
+  size_t UnitSize = GetCurrentUnitNoThreadCheck(&UnitData);
+  if (UnitSize <= kMaxUnitSizeToPrint) {
+    PrintHexArray(UnitData, UnitSize, "\n");
+    PrintASCII(UnitData, UnitSize, "\n");
   }
   WriteUnitToFileWithPrefix(
-      {CurrentUnitData, CurrentUnitData + CurrentUnitSize}, Prefix);
+      {UnitData, UnitData + UnitSize}, Prefix);
 }
 
 NO_SANITIZE_MEMORY
 void Fuzzer::DeathCallback() {
-  if (CurrentUnitSize) {
-    Printf("DEATH:\n");
-    DumpCurrentUnit("crash-");
-  }
+  DumpCurrentUnit("crash-");
   PrintFinalStats();
 }
 
@@ -224,11 +223,15 @@ void Fuzzer::InterruptCallback() {
 NO_SANITIZE_MEMORY
 void Fuzzer::AlarmCallback() {
   assert(Options.UnitTimeoutSec > 0);
+  if (!InFuzzingThread()) return;
+  const uint8_t *UnitData;
+  size_t UnitSize = GetCurrentUnitInFuzzingThead(&UnitData);
   if (InOOMState) {
-    Printf("==%d== ERROR: libFuzzer: out-of-memory (used: %zdMb; limit: %zdMb)\n",
-           GetPid(), GetPeakRSSMb(), Options.RssLimitMb);
+    Printf(
+        "==%d== ERROR: libFuzzer: out-of-memory (used: %zdMb; limit: %zdMb)\n",
+        GetPid(), GetPeakRSSMb(), Options.RssLimitMb);
     Printf("   To change the out-of-memory limit use -rss_limit_mb=<N>\n");
-    if (CurrentUnitSize && CurrentUnitData) {
+    if (UnitSize && UnitData) {
       DumpCurrentUnit("oom-");
       if (__sanitizer_print_stack_trace)
         __sanitizer_print_stack_trace();
@@ -238,7 +241,7 @@ void Fuzzer::AlarmCallback() {
     _Exit(Options.ErrorExitCode); // Stop right now.
   }
 
-  if (!CurrentUnitSize)
+  if (!UnitSize)
     return; // We have not started running units yet.
   size_t Seconds =
       duration_cast<seconds>(system_clock::now() - UnitStartTime).count();
@@ -498,6 +501,22 @@ void __sanitizer_free_hook(void *ptr) {
 }
 }  // extern "C"
 
+void Fuzzer::SetCurrentUnit(const uint8_t *Data, size_t Size) {
+  assert(InFuzzingThread());
+  CurrentUnitSize = Size;
+  CurrentUnitData = Data;
+}
+
+size_t Fuzzer::GetCurrentUnitNoThreadCheck(const uint8_t **Data) const {
+  *Data = CurrentUnitData;
+  return CurrentUnitSize;
+}
+
+size_t Fuzzer::GetCurrentUnitInFuzzingThead(const uint8_t **Data) const {
+  assert(InFuzzingThread());
+  return GetCurrentUnitNoThreadCheck(Data);
+}
+
 void Fuzzer::ExecuteCallback(const uint8_t *Data, size_t Size) {
   UnitStartTime = system_clock::now();
   // We copy the contents of Unit into a separate heap buffer
@@ -505,14 +524,12 @@ void Fuzzer::ExecuteCallback(const uint8
   std::unique_ptr<uint8_t[]> DataCopy(new uint8_t[Size]);
   memcpy(DataCopy.get(), Data, Size);
   AssignTaintLabels(DataCopy.get(), Size);
-  CurrentUnitData = DataCopy.get();
-  CurrentUnitSize = Size;
+  SetCurrentUnit(DataCopy.get(), Size);
   AllocTracer.Start();
   int Res = CB(DataCopy.get(), Size);
   (void)Res;
   HasMoreMallocsThanFrees = AllocTracer.Stop();
-  CurrentUnitSize = 0;
-  CurrentUnitData = nullptr;
+  SetCurrentUnit(nullptr, 0);
   assert(Res == 0);
 }
 
@@ -672,8 +689,7 @@ void Fuzzer::TryDetectingAMemoryLeak(con
     if (DuringInitialCorpusExecution)
       Printf("\nINFO: a leak has been found in the initial corpus.\n\n");
     Printf("INFO: to ignore leaks on libFuzzer side use -detect_leaks=0.\n\n");
-    CurrentUnitData = Data;
-    CurrentUnitSize = Size;
+    SetCurrentUnit(Data, Size);
     DumpCurrentUnit("leak-");
     PrintFinalStats();
     _Exit(Options.ErrorExitCode);  // not exit() to disable lsan further on.

Modified: llvm/trunk/lib/Fuzzer/test/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/test/CMakeLists.txt?rev=270929&r1=270928&r2=270929&view=diff
==============================================================================
--- llvm/trunk/lib/Fuzzer/test/CMakeLists.txt (original)
+++ llvm/trunk/lib/Fuzzer/test/CMakeLists.txt Thu May 26 17:17:32 2016
@@ -58,6 +58,7 @@ set(Tests
   SimpleFnAdapterTest
   SimpleHashTest
   SimpleTest
+  SimpleThreadedTest
   SpamyTest
   StrcmpTest
   StrncmpTest

Added: llvm/trunk/lib/Fuzzer/test/SimpleThreadedTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/test/SimpleThreadedTest.cpp?rev=270929&view=auto
==============================================================================
--- llvm/trunk/lib/Fuzzer/test/SimpleThreadedTest.cpp (added)
+++ llvm/trunk/lib/Fuzzer/test/SimpleThreadedTest.cpp Thu May 26 17:17:32 2016
@@ -0,0 +1,25 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Threaded test for a fuzzer. The fuzzer should find "H"
+#include <assert.h>
+#include <cstdint>
+#include <cstddef>
+#include <cstring>
+#include <iostream>
+#include <thread>
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+  auto C = [&] {
+    if (Size >= 2 && Data[0] == 'H') {
+        std::cout << "BINGO; Found the target, exiting\n";
+        abort();
+    }
+  };
+  std::thread T[] = {std::thread(C), std::thread(C), std::thread(C),
+                     std::thread(C), std::thread(C), std::thread(C)};
+  for (auto &X : T)
+    X.join();
+  return 0;
+}
+

Modified: llvm/trunk/lib/Fuzzer/test/fuzzer-leak.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/test/fuzzer-leak.test?rev=270929&r1=270928&r2=270929&view=diff
==============================================================================
--- llvm/trunk/lib/Fuzzer/test/fuzzer-leak.test (original)
+++ llvm/trunk/lib/Fuzzer/test/fuzzer-leak.test Thu May 26 17:17:32 2016
@@ -3,7 +3,6 @@ LEAK_DURING: ERROR: LeakSanitizer: detec
 LEAK_DURING: Direct leak of 4 byte(s) in 1 object(s) allocated from:
 LEAK_DURING-NOT: DONE
 LEAK_DURING-NOT: Done
-LEAK_DURING-NOT: DEATH:
 
 RUN: not LLVMFuzzer-LeakTest -runs=0 -detect_leaks=1 %S 2>&1 | FileCheck %s --check-prefix=LEAK_IN_CORPUS
 LEAK_IN_CORPUS: ERROR: LeakSanitizer: detected memory leaks
@@ -14,7 +13,6 @@ RUN: not LLVMFuzzer-LeakTest -runs=10000
 RUN: not LLVMFuzzer-LeakTest -runs=100000                 2>&1 | FileCheck %s --check-prefix=LEAK_DURING
 LEAK_AFTER: Done 100000 runs in
 LEAK_AFTER: ERROR: LeakSanitizer: detected memory leaks
-LEAK_AFTER-NOT: DEATH:
 
 RUN: not LLVMFuzzer-LeakTimeoutTest -timeout=1 2>&1 | FileCheck %s --check-prefix=LEAK_TIMEOUT
 LEAK_TIMEOUT: ERROR: libFuzzer: timeout after




More information about the llvm-commits mailing list