[libFuzzer] provide a plain C interface for custom mutators (experimental)

llvm-svn: 260794
This commit is contained in:
Kostya Serebryany 2016-02-13 02:29:38 +00:00
parent 94d1855e08
commit 22cc5e2375
6 changed files with 65 additions and 2 deletions

View File

@ -58,6 +58,10 @@ size_t Mutate(uint8_t *Data, size_t Size, size_t MaxSize,
return MD.Mutate(Data, Size, MaxSize);
}
size_t Mutate(uint8_t *Data, size_t Size, size_t MaxSize, unsigned int Seed) {
FuzzerRandom_mt19937 R(Seed);
MutationDispatcher MD(R);
return MD.Mutate(Data, Size, MaxSize);
}
} // namespace fuzzer.

View File

@ -22,6 +22,22 @@
#include <vector>
#include <string>
// Plain C interface. Should be sufficient for most uses.
extern "C" {
// The target function, mandatory.
// Must return 0.
int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size);
// The initialization function, optional.
int LLVMFuzzerInitialize(int *argc, char ***argv);
// Custom mutator, optional.
// Mutates raw data in [Data, Data+Size] inplace.
// Returns the new size, which is not greater than MaxSize.
// Given the same Seed produces the same mutation.
size_t LLVMFuzzerCustomMutator(uint8_t *Data, size_t Size, size_t MaxSize,
unsigned int Seed);
} // extern "C"
namespace fuzzer {
/// Returns an int 0. Values other than zero are reserved for future.
@ -93,6 +109,8 @@ class FuzzerRandom_mt19937 : public FuzzerRandomBase {
size_t Mutate(uint8_t *Data, size_t Size, size_t MaxSize,
FuzzerRandomBase &Rand);
size_t Mutate(uint8_t *Data, size_t Size, size_t MaxSize, unsigned int Seed);
class MutationDispatcher;
/** An abstract class that allows to use user-supplied mutators with libFuzzer.

View File

@ -35,6 +35,10 @@ __attribute__((weak)) uintptr_t
__sanitizer_update_counter_bitset_and_clear_counters(uint8_t *bitset);
__attribute__((weak)) uintptr_t
__sanitizer_get_coverage_pc_buffer(uintptr_t **data);
__attribute__((weak)) size_t LLVMFuzzerCustomMutator(uint8_t *Data, size_t Size,
size_t MaxSize,
unsigned int Seed);
}
namespace fuzzer {
@ -407,7 +411,12 @@ void Fuzzer::MutateAndTestOne() {
for (int i = 0; i < Options.MutateDepth; i++) {
size_t Size = U.size();
U.resize(Options.MaxLen);
size_t NewSize = USF.Mutate(U.data(), Size, U.size());
size_t NewSize = 0;
if (LLVMFuzzerCustomMutator)
NewSize = LLVMFuzzerCustomMutator(U.data(), Size, U.size(),
USF.GetRand().Rand());
else
NewSize = USF.Mutate(U.data(), Size, U.size());
assert(NewSize > 0 && "Mutator returned empty unit");
assert(NewSize <= (size_t)Options.MaxLen &&
"Mutator return overisized unit");

View File

@ -16,6 +16,7 @@ set(Tests
BufferOverflowOnInput
CallerCalleeTest
CounterTest
CustomMutatorTest
FourIndependentBranchesTest
FullCoverageSetTest
InitializeTest

View File

@ -0,0 +1,27 @@
// Simple test for a cutom mutator.
#include <assert.h>
#include <cstdint>
#include <cstdlib>
#include <cstddef>
#include <iostream>
#include "FuzzerInterface.h"
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
assert(Data);
if (Size > 0 && Data[0] == 'F') {
std::cout << "BINGO; Found the target, exiting\n";
exit(1);
}
return 0;
}
extern "C" size_t LLVMFuzzerCustomMutator(uint8_t *Data, size_t Size,
size_t MaxSize, unsigned int Seed) {
static bool Printed;
if (!Printed) {
std::cerr << "In LLVMFuzzerCustomMutator\n";
Printed = true;
}
return fuzzer::Mutate(Data, Size, MaxSize, Seed);
}

View File

@ -66,3 +66,7 @@ RUN: LLVMFuzzer-NthRunCrashTest %t/NthRunCrashTest.in
RUN: LLVMFuzzer-NthRunCrashTest %t/NthRunCrashTest.in -runs=10
RUN: not LLVMFuzzer-NthRunCrashTest %t/NthRunCrashTest.in -runs=10000 2>&1 | FileCheck %s
RUN: rm %t/NthRunCrashTest.in
RUN: not LLVMFuzzer-CustomMutatorTest 2>&1 | FileCheck %s --check-prefix=LLVMFuzzerCustomMutator
LLVMFuzzerCustomMutator: In LLVMFuzzerCustomMutator
LLVMFuzzerCustomMutator: BINGO