[llvm] r257701 - [libFuzzer] make sure we find buffer overflow in the input buffer. Previously, re-using the same vector object was hiding buffer overflows (unless we used annotated vector)

Kostya Serebryany via llvm-commits llvm-commits at lists.llvm.org
Wed Jan 13 15:02:30 PST 2016


Author: kcc
Date: Wed Jan 13 17:02:30 2016
New Revision: 257701

URL: http://llvm.org/viewvc/llvm-project?rev=257701&view=rev
Log:
[libFuzzer] make sure we find buffer overflow in the input buffer. Previously, re-using the same vector object was hiding buffer overflows (unless we used annotated vector)

Added:
    llvm/trunk/lib/Fuzzer/test/BufferOverflowOnInput.cpp
Modified:
    llvm/trunk/lib/Fuzzer/FuzzerInternal.h
    llvm/trunk/lib/Fuzzer/FuzzerLoop.cpp
    llvm/trunk/lib/Fuzzer/FuzzerTraceState.cpp
    llvm/trunk/lib/Fuzzer/test/CMakeLists.txt
    llvm/trunk/lib/Fuzzer/test/fuzzer.test

Modified: llvm/trunk/lib/Fuzzer/FuzzerInternal.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/FuzzerInternal.h?rev=257701&r1=257700&r2=257701&view=diff
==============================================================================
--- llvm/trunk/lib/Fuzzer/FuzzerInternal.h (original)
+++ llvm/trunk/lib/Fuzzer/FuzzerInternal.h Wed Jan 13 17:02:30 2016
@@ -106,6 +106,7 @@ class Fuzzer {
   void Drill();
   void ShuffleAndMinimize();
   void InitializeTraceState();
+  void AssignTaintLabels(uint8_t *Data, size_t Size);
   size_t CorpusSize() const { return Corpus.size(); }
   void ReadDir(const std::string &Path, long *Epoch) {
     Printf("Loading corpus: %s\n", Path.c_str());

Modified: llvm/trunk/lib/Fuzzer/FuzzerLoop.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/FuzzerLoop.cpp?rev=257701&r1=257700&r2=257701&view=diff
==============================================================================
--- llvm/trunk/lib/Fuzzer/FuzzerLoop.cpp (original)
+++ llvm/trunk/lib/Fuzzer/FuzzerLoop.cpp Wed Jan 13 17:02:30 2016
@@ -11,6 +11,8 @@
 
 #include "FuzzerInternal.h"
 #include <algorithm>
+#include <cstring>
+#include <memory>
 
 #if defined(__has_include)
 # if __has_include(<sanitizer/coverage_interface.h>)
@@ -240,11 +242,12 @@ void Fuzzer::RunOneAndUpdateCorpus(Unit
 }
 
 void Fuzzer::ExecuteCallback(const Unit &U) {
-  const uint8_t *Data = U.data();
-  uint8_t EmptyData;
-  if (!Data) 
-    Data = &EmptyData;
-  int Res = USF.TargetFunction(Data, U.size());
+  // We copy the contents of Unit into a separate heap buffer
+  // so that we reliably find buffer overflows in it.
+  std::unique_ptr<uint8_t[]> Data(new uint8_t[U.size()]);
+  memcpy(Data.get(), U.data(), U.size());
+  AssignTaintLabels(Data.get(), U.size());
+  int Res = USF.TargetFunction(Data.get(), U.size());
   (void)Res;
   assert(Res == 0);
 }

Modified: llvm/trunk/lib/Fuzzer/FuzzerTraceState.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/FuzzerTraceState.cpp?rev=257701&r1=257700&r2=257701&view=diff
==============================================================================
--- llvm/trunk/lib/Fuzzer/FuzzerTraceState.cpp (original)
+++ llvm/trunk/lib/Fuzzer/FuzzerTraceState.cpp Wed Jan 13 17:02:30 2016
@@ -451,9 +451,6 @@ static TraceState *TS;
 
 void Fuzzer::StartTraceRecording() {
   if (!TS) return;
-  if (ReallyHaveDFSan())
-    for (size_t i = 0; i < static_cast<size_t>(Options.MaxLen); i++)
-      dfsan_set_label(i + 1, &CurrentUnit[i], 1);
   TS->StartTraceRecording();
 }
 
@@ -462,18 +459,24 @@ void Fuzzer::StopTraceRecording() {
   TS->StopTraceRecording();
 }
 
+void Fuzzer::AssignTaintLabels(uint8_t *Data, size_t Size) {
+  if (!Options.UseTraces) return;
+  if (!ReallyHaveDFSan()) return;
+  for (size_t i = 0; i < Size; i++)
+    dfsan_set_label(i + 1, &Data[i], 1);
+}
+
 void Fuzzer::InitializeTraceState() {
   if (!Options.UseTraces) return;
   TS = new TraceState(USF, Options, CurrentUnit);
-  CurrentUnit.resize(Options.MaxLen);
-  // The rest really requires DFSan.
-  if (!ReallyHaveDFSan()) return;
-  for (size_t i = 0; i < static_cast<size_t>(Options.MaxLen); i++) {
-    dfsan_label L = dfsan_create_label("input", (void*)(i + 1));
-    // We assume that no one else has called dfsan_create_label before.
-    if (L != i + 1) {
-      Printf("DFSan labels are not starting from 1, exiting\n");
-      exit(1);
+  if (ReallyHaveDFSan()) {
+    for (size_t i = 0; i < static_cast<size_t>(Options.MaxLen); i++) {
+      dfsan_label L = dfsan_create_label("input", (void *)(i + 1));
+      // We assume that no one else has called dfsan_create_label before.
+      if (L != i + 1) {
+        Printf("DFSan labels are not starting from 1, exiting\n");
+        exit(1);
+      }
     }
   }
 }

Added: llvm/trunk/lib/Fuzzer/test/BufferOverflowOnInput.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/test/BufferOverflowOnInput.cpp?rev=257701&view=auto
==============================================================================
--- llvm/trunk/lib/Fuzzer/test/BufferOverflowOnInput.cpp (added)
+++ llvm/trunk/lib/Fuzzer/test/BufferOverflowOnInput.cpp Wed Jan 13 17:02:30 2016
@@ -0,0 +1,20 @@
+// Simple test for a fuzzer. The fuzzer must find the string "Hi!".
+#include <assert.h>
+#include <cstdint>
+#include <cstdlib>
+#include <cstddef>
+#include <iostream>
+
+static volatile bool SeedLargeBuffer;
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+  assert(Data);
+  if (Size >= 4)
+    SeedLargeBuffer = true;
+  if (Size == 3 && SeedLargeBuffer && Data[3]) {
+    std::cout << "Woops, reading Data[3] w/o crashing\n";
+    exit(1);
+  }
+  return 0;
+}
+

Modified: llvm/trunk/lib/Fuzzer/test/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/test/CMakeLists.txt?rev=257701&r1=257700&r2=257701&view=diff
==============================================================================
--- llvm/trunk/lib/Fuzzer/test/CMakeLists.txt (original)
+++ llvm/trunk/lib/Fuzzer/test/CMakeLists.txt Wed Jan 13 17:02:30 2016
@@ -13,6 +13,7 @@ set(DFSanTests
   )
 
 set(Tests
+  BufferOverflowOnInput
   CallerCalleeTest
   CounterTest
   FourIndependentBranchesTest

Modified: llvm/trunk/lib/Fuzzer/test/fuzzer.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/test/fuzzer.test?rev=257701&r1=257700&r2=257701&view=diff
==============================================================================
--- llvm/trunk/lib/Fuzzer/test/fuzzer.test (original)
+++ llvm/trunk/lib/Fuzzer/test/fuzzer.test Wed Jan 13 17:02:30 2016
@@ -34,3 +34,6 @@ PCS:{{^0x[a-f0-9]+}}
 PCS:NEW
 PCS:BINGO
 
+RUN: not LLVMFuzzer-BufferOverflowOnInput 2>&1 | FileCheck %s --check-prefix=OOB
+OOB: AddressSanitizer: heap-buffer-overflow
+OOB: is located 0 bytes to the right of 3-byte region




More information about the llvm-commits mailing list