Skip to content

Commit

Permalink
[libFuzzer] use the indirect caller-callee counter as an independent …
Browse files Browse the repository at this point in the history
…search heuristic

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@251078 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
kcc committed Oct 22, 2015
1 parent 41180c6 commit 7bcc4cd
Show file tree
Hide file tree
Showing 7 changed files with 79 additions and 1 deletion.
1 change: 1 addition & 0 deletions lib/Fuzzer/FuzzerDriver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,7 @@ int FuzzerDriver(const std::vector<std::string> &Args,
Options.MutateDepth = Flags.mutate_depth;
Options.ExitOnFirst = Flags.exit_on_first;
Options.UseCounters = Flags.use_counters;
Options.UseIndirCalls = Flags.use_indir_calls;
Options.UseTraces = Flags.use_traces;
Options.ShuffleAtStartUp = Flags.shuffle;
Options.PreferSmallDuringInitialShuffle =
Expand Down
1 change: 1 addition & 0 deletions lib/Fuzzer/FuzzerFlags.def
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ FUZZER_FLAG_INT(
"If 1, the minimized corpus is saved into the first input directory. "
"Example: ./fuzzer -save_minimized_corpus=1 NEW_EMPTY_DIR OLD_CORPUS")
FUZZER_FLAG_INT(use_counters, 1, "Use coverage counters")
FUZZER_FLAG_INT(use_indir_calls, 1, "Use indirect caller-callee counters")
FUZZER_FLAG_INT(use_traces, 0, "Experimental: use instruction traces")
FUZZER_FLAG_INT(jobs, 0, "Number of jobs to run. If jobs >= 1 we spawn"
" this number of jobs in separate worker processes"
Expand Down
3 changes: 3 additions & 0 deletions lib/Fuzzer/FuzzerInternal.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ class Fuzzer {
int MutateDepth = 5;
bool ExitOnFirst = false;
bool UseCounters = false;
bool UseIndirCalls = true;
bool UseTraces = false;
bool UseFullCoverageSet = false;
bool Reload = true;
Expand Down Expand Up @@ -134,6 +135,7 @@ class Fuzzer {
void SyncCorpus();

size_t RecordBlockCoverage();
size_t RecordCallerCalleeCoverage();
void PrepareCoverageBeforeRun();
bool CheckCoverageAfterRun();

Expand Down Expand Up @@ -176,6 +178,7 @@ class Fuzzer {
long TimeOfLongestUnitInSeconds = 0;
long EpochOfLastReadOfOutputCorpus = 0;
size_t LastRecordedBlockCoverage = 0;
size_t LastRecordedCallerCalleeCoverage = 0;
};

class SimpleUserSuppliedFuzzer: public UserSuppliedFuzzer {
Expand Down
15 changes: 14 additions & 1 deletion lib/Fuzzer/FuzzerLoop.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,8 @@ void Fuzzer::PrintStats(const char *Where, const char *End) {
Printf(" cov: %zd", LastRecordedBlockCoverage);
if (auto TB = TotalBits())
Printf(" bits: %zd", TB);
if (LastRecordedCallerCalleeCoverage)
Printf(" indir: %zd", LastRecordedCallerCalleeCoverage);
Printf(" units: %zd exec/s: %zd", Corpus.size(), ExecPerSec);
if (TotalNumberOfExecutedTraceBasedMutations)
Printf(" tbm: %zd", TotalNumberOfExecutedTraceBasedMutations);
Expand Down Expand Up @@ -202,23 +204,34 @@ size_t Fuzzer::RecordBlockCoverage() {
return LastRecordedBlockCoverage = __sanitizer_get_total_unique_coverage();
}

size_t Fuzzer::RecordCallerCalleeCoverage() {
if (!Options.UseIndirCalls)
return 0;
return LastRecordedCallerCalleeCoverage =
__sanitizer_get_total_unique_caller_callee_pairs();
}

void Fuzzer::PrepareCoverageBeforeRun() {
if (Options.UseCounters) {
size_t NumCounters = __sanitizer_get_number_of_counters();
CounterBitmap.resize(NumCounters);
__sanitizer_update_counter_bitset_and_clear_counters(0);
}
RecordBlockCoverage();
RecordCallerCalleeCoverage();
}

bool Fuzzer::CheckCoverageAfterRun() {
size_t OldCoverage = LastRecordedBlockCoverage;
size_t NewCoverage = RecordBlockCoverage();
size_t OldCallerCalleeCoverage = LastRecordedCallerCalleeCoverage;
size_t NewCallerCalleeCoverage = RecordCallerCalleeCoverage();
size_t NumNewBits = 0;
if (Options.UseCounters)
NumNewBits = __sanitizer_update_counter_bitset_and_clear_counters(
CounterBitmap.data());
return NewCoverage > OldCoverage || NumNewBits;
return NewCoverage > OldCoverage ||
NewCallerCalleeCoverage > OldCallerCalleeCoverage || NumNewBits;
}

void Fuzzer::WriteToOutputCorpus(const Unit &U) {
Expand Down
1 change: 1 addition & 0 deletions lib/Fuzzer/test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ set(DFSanTests
)

set(Tests
CallerCalleeTest
CounterTest
FourIndependentBranchesTest
FullCoverageSetTest
Expand Down
56 changes: 56 additions & 0 deletions lib/Fuzzer/test/CallerCalleeTest.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
// Simple test for a fuzzer.
// Try to find the target using the indirect caller-callee pairs.
#include <cstdint>
#include <cstdlib>
#include <cstddef>
#include <cstring>
#include <iostream>

typedef void (*F)();
static F t[256];

void f34() {
std::cerr << "BINGO\n";
exit(1);
}
void f23() { t[(unsigned)'d'] = f34;}
void f12() { t[(unsigned)'c'] = f23;}
void f01() { t[(unsigned)'b'] = f12;}
void f00() {}

static F t0[256] = {
f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00,
f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00,
f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00,
f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00,
f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00,
f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00,
f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00,
f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00,
f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00,
f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00,
f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00,
f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00,
f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00,
f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00,
f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00,
f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00,
};

extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
if (Size < 4) return 0;
// Spoof the counters.
for (int i = 0; i < 200; i++) {
f23();
f12();
f01();
}
memcpy(t, t0, sizeof(t));
t[(unsigned)'a'] = f01;
t[Data[0]]();
t[Data[1]]();
t[Data[2]]();
t[Data[3]]();
return 0;
}

3 changes: 3 additions & 0 deletions lib/Fuzzer/test/fuzzer.test
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ NullDerefTestPrefix: Test unit written to ZZZcrash-

RUN: not LLVMFuzzer-CounterTest -use_counters=1 -max_len=6 -seed=1 -timeout=15 2>&1 | FileCheck %s

RUN: not LLVMFuzzer-CallerCalleeTest -max_len=6 -seed=1 -timeout=15 2>&1 | FileCheck %s
RUN: LLVMFuzzer-CallerCalleeTest -use_indir_calls=0 -max_len=6 -seed=1 -runs=1000000 2>&1 | FileCheck %s --check-prefix=Done1000000

RUN: not LLVMFuzzer-SimpleCmpTest -use_traces=1 -seed=1 -runs=1000000 -timeout=5 2>&1 | FileCheck %s

RUN: not LLVMFuzzer-UserSuppliedFuzzerTest -seed=1 -timeout=15 2>&1 | FileCheck %s
Expand Down

0 comments on commit 7bcc4cd

Please sign in to comment.