[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)

llvm-svn: 257701
This commit is contained in:
Kostya Serebryany 2016-01-13 23:02:30 +00:00
parent 9913322327
commit d50a3eedb4
6 changed files with 48 additions and 17 deletions

View File

@ -106,6 +106,7 @@ class Fuzzer {
void Drill(); void Drill();
void ShuffleAndMinimize(); void ShuffleAndMinimize();
void InitializeTraceState(); void InitializeTraceState();
void AssignTaintLabels(uint8_t *Data, size_t Size);
size_t CorpusSize() const { return Corpus.size(); } size_t CorpusSize() const { return Corpus.size(); }
void ReadDir(const std::string &Path, long *Epoch) { void ReadDir(const std::string &Path, long *Epoch) {
Printf("Loading corpus: %s\n", Path.c_str()); Printf("Loading corpus: %s\n", Path.c_str());

View File

@ -11,6 +11,8 @@
#include "FuzzerInternal.h" #include "FuzzerInternal.h"
#include <algorithm> #include <algorithm>
#include <cstring>
#include <memory>
#if defined(__has_include) #if defined(__has_include)
# if __has_include(<sanitizer/coverage_interface.h>) # if __has_include(<sanitizer/coverage_interface.h>)
@ -240,11 +242,12 @@ void Fuzzer::RunOneAndUpdateCorpus(Unit &U) {
} }
void Fuzzer::ExecuteCallback(const Unit &U) { void Fuzzer::ExecuteCallback(const Unit &U) {
const uint8_t *Data = U.data(); // We copy the contents of Unit into a separate heap buffer
uint8_t EmptyData; // so that we reliably find buffer overflows in it.
if (!Data) std::unique_ptr<uint8_t[]> Data(new uint8_t[U.size()]);
Data = &EmptyData; memcpy(Data.get(), U.data(), U.size());
int Res = USF.TargetFunction(Data, U.size()); AssignTaintLabels(Data.get(), U.size());
int Res = USF.TargetFunction(Data.get(), U.size());
(void)Res; (void)Res;
assert(Res == 0); assert(Res == 0);
} }

View File

@ -451,9 +451,6 @@ static TraceState *TS;
void Fuzzer::StartTraceRecording() { void Fuzzer::StartTraceRecording() {
if (!TS) return; 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(); TS->StartTraceRecording();
} }
@ -462,18 +459,24 @@ void Fuzzer::StopTraceRecording() {
TS->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() { void Fuzzer::InitializeTraceState() {
if (!Options.UseTraces) return; if (!Options.UseTraces) return;
TS = new TraceState(USF, Options, CurrentUnit); TS = new TraceState(USF, Options, CurrentUnit);
CurrentUnit.resize(Options.MaxLen); if (ReallyHaveDFSan()) {
// The rest really requires DFSan. for (size_t i = 0; i < static_cast<size_t>(Options.MaxLen); i++) {
if (!ReallyHaveDFSan()) return; dfsan_label L = dfsan_create_label("input", (void *)(i + 1));
for (size_t i = 0; i < static_cast<size_t>(Options.MaxLen); i++) { // We assume that no one else has called dfsan_create_label before.
dfsan_label L = dfsan_create_label("input", (void*)(i + 1)); if (L != i + 1) {
// We assume that no one else has called dfsan_create_label before. Printf("DFSan labels are not starting from 1, exiting\n");
if (L != i + 1) { exit(1);
Printf("DFSan labels are not starting from 1, exiting\n"); }
exit(1);
} }
} }
} }

View File

@ -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;
}

View File

@ -13,6 +13,7 @@ set(DFSanTests
) )
set(Tests set(Tests
BufferOverflowOnInput
CallerCalleeTest CallerCalleeTest
CounterTest CounterTest
FourIndependentBranchesTest FourIndependentBranchesTest

View File

@ -34,3 +34,6 @@ PCS:{{^0x[a-f0-9]+}}
PCS:NEW PCS:NEW
PCS:BINGO 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