[libFuzzer] simplify the code, NFC

llvm-svn: 279697
This commit is contained in:
Kostya Serebryany 2016-08-25 01:25:03 +00:00
parent 381fc0ee3c
commit f67357c671
2 changed files with 95 additions and 105 deletions

View File

@ -19,7 +19,6 @@
#include <climits>
#include <cstddef>
#include <cstdlib>
#include <memory>
#include <random>
#include <string.h>
#include <string>
@ -360,8 +359,6 @@ private:
std::vector<Mutator> DefaultMutators;
};
class CoverageController;
class Fuzzer {
public:
@ -488,6 +485,11 @@ private:
void DumpCurrentUnit(const char *Prefix);
void DeathCallback();
void ResetEdgeCoverage();
void ResetCounters();
void PrepareCounters(Fuzzer::Coverage *C);
bool RecordMaxCoverage(Fuzzer::Coverage *C);
void LazyAllocateCurrentUnitData();
uint8_t *CurrentUnitData = nullptr;
std::atomic<size_t> CurrentUnitSize;
@ -513,7 +515,10 @@ private:
// Maximum recorded coverage.
Coverage MaxCoverage;
std::unique_ptr<CoverageController> CController;
// For -print_new_cov_pcs
uintptr_t* PcBuffer = nullptr;
size_t PcBufferLen = 0;
// Need to know our own thread.
static thread_local bool IsMyThread;

View File

@ -53,102 +53,82 @@ static void MissingExternalApiFunction(const char *FnName) {
// Only one Fuzzer per process.
static Fuzzer *F;
// Only one CoverageController per process should be created.
class CoverageController {
public:
explicit CoverageController(const FuzzingOptions &Options)
: Options(Options) {
if (Options.PrintNewCovPcs) {
PcBufferLen = 1 << 24;
PcBuffer = new uintptr_t[PcBufferLen];
EF->__sanitizer_set_coverage_pc_buffer(PcBuffer, PcBufferLen);
}
void Fuzzer::ResetEdgeCoverage() {
CHECK_EXTERNAL_FUNCTION(__sanitizer_reset_coverage);
EF->__sanitizer_reset_coverage();
}
void Fuzzer::ResetCounters() {
if (Options.UseCounters) {
EF->__sanitizer_update_counter_bitset_and_clear_counters(0);
}
}
void Fuzzer::PrepareCounters(Fuzzer::Coverage *C) {
if (Options.UseCounters) {
size_t NumCounters = EF->__sanitizer_get_number_of_counters();
C->CounterBitmap.resize(NumCounters);
}
}
// Records data to a maximum coverage tracker. Returns true if additional
// coverage was discovered.
bool Fuzzer::RecordMaxCoverage(Fuzzer::Coverage *C) {
bool Res = false;
uint64_t NewBlockCoverage = EF->__sanitizer_get_total_unique_coverage();
if (NewBlockCoverage > C->BlockCoverage) {
Res = true;
C->BlockCoverage = NewBlockCoverage;
}
uintptr_t* pc_buffer() const { return PcBuffer; }
void Reset() {
CHECK_EXTERNAL_FUNCTION(__sanitizer_reset_coverage);
EF->__sanitizer_reset_coverage();
}
void ResetCounters() {
if (Options.UseCounters) {
EF->__sanitizer_update_counter_bitset_and_clear_counters(0);
}
}
void Prepare(Fuzzer::Coverage *C) {
if (Options.UseCounters) {
size_t NumCounters = EF->__sanitizer_get_number_of_counters();
C->CounterBitmap.resize(NumCounters);
}
}
// Records data to a maximum coverage tracker. Returns true if additional
// coverage was discovered.
bool RecordMax(Fuzzer::Coverage *C) {
bool Res = false;
uint64_t NewBlockCoverage = EF->__sanitizer_get_total_unique_coverage();
if (NewBlockCoverage > C->BlockCoverage) {
if (Options.UseIndirCalls &&
EF->__sanitizer_get_total_unique_caller_callee_pairs) {
uint64_t NewCallerCalleeCoverage =
EF->__sanitizer_get_total_unique_caller_callee_pairs();
if (NewCallerCalleeCoverage > C->CallerCalleeCoverage) {
Res = true;
C->BlockCoverage = NewBlockCoverage;
C->CallerCalleeCoverage = NewCallerCalleeCoverage;
}
if (Options.UseIndirCalls &&
EF->__sanitizer_get_total_unique_caller_callee_pairs) {
uint64_t NewCallerCalleeCoverage =
EF->__sanitizer_get_total_unique_caller_callee_pairs();
if (NewCallerCalleeCoverage > C->CallerCalleeCoverage) {
Res = true;
C->CallerCalleeCoverage = NewCallerCalleeCoverage;
}
}
if (Options.UseCounters) {
uint64_t CounterDelta =
EF->__sanitizer_update_counter_bitset_and_clear_counters(
C->CounterBitmap.data());
if (CounterDelta > 0) {
Res = true;
C->CounterBitmapBits += CounterDelta;
}
}
size_t NewPCMapBits = PCMapMergeFromCurrent(C->PCMap);
if (NewPCMapBits > C->PCMapBits) {
Res = true;
C->PCMapBits = NewPCMapBits;
}
size_t NewVPMapBits = VPMapMergeFromCurrent(C->VPMap);
if (NewVPMapBits > C->VPMapBits) {
Res = true;
C->VPMapBits = NewVPMapBits;
}
if (EF->__sanitizer_get_coverage_pc_buffer_pos) {
uint64_t NewPcBufferPos = EF->__sanitizer_get_coverage_pc_buffer_pos();
if (NewPcBufferPos > C->PcBufferPos) {
Res = true;
C->PcBufferPos = NewPcBufferPos;
}
if (PcBufferLen && NewPcBufferPos >= PcBufferLen) {
Printf("ERROR: PC buffer overflow\n");
_Exit(1);
}
}
return Res;
}
private:
const FuzzingOptions Options;
uintptr_t* PcBuffer = nullptr;
size_t PcBufferLen = 0;
};
if (Options.UseCounters) {
uint64_t CounterDelta =
EF->__sanitizer_update_counter_bitset_and_clear_counters(
C->CounterBitmap.data());
if (CounterDelta > 0) {
Res = true;
C->CounterBitmapBits += CounterDelta;
}
}
size_t NewPCMapBits = PCMapMergeFromCurrent(C->PCMap);
if (NewPCMapBits > C->PCMapBits) {
Res = true;
C->PCMapBits = NewPCMapBits;
}
size_t NewVPMapBits = VPMapMergeFromCurrent(C->VPMap);
if (NewVPMapBits > C->VPMapBits) {
Res = true;
C->VPMapBits = NewVPMapBits;
}
if (EF->__sanitizer_get_coverage_pc_buffer_pos) {
uint64_t NewPcBufferPos = EF->__sanitizer_get_coverage_pc_buffer_pos();
if (NewPcBufferPos > C->PcBufferPos) {
Res = true;
C->PcBufferPos = NewPcBufferPos;
}
if (PcBufferLen && NewPcBufferPos >= PcBufferLen) {
Printf("ERROR: PC buffer overflow\n");
_Exit(1);
}
}
return Res;
}
// Leak detection is expensive, so we first check if there were more mallocs
// than frees (using the sanitizer malloc hooks) and only then try to call lsan.
@ -173,8 +153,7 @@ void FreeHook(const volatile void *ptr) {
}
Fuzzer::Fuzzer(UserCallback CB, MutationDispatcher &MD, FuzzingOptions Options)
: CB(CB), MD(MD), Options(Options),
CController(new CoverageController(Options)) {
: CB(CB), MD(MD), Options(Options) {
SetDeathCallback();
InitializeTraceState();
assert(!F);
@ -183,6 +162,12 @@ Fuzzer::Fuzzer(UserCallback CB, MutationDispatcher &MD, FuzzingOptions Options)
IsMyThread = true;
if (Options.DetectLeaks && EF->__sanitizer_install_malloc_and_free_hooks)
EF->__sanitizer_install_malloc_and_free_hooks(MallocHook, FreeHook);
if (Options.PrintNewCovPcs) {
PcBufferLen = 1 << 24;
PcBuffer = new uintptr_t[PcBufferLen];
EF->__sanitizer_set_coverage_pc_buffer(PcBuffer, PcBufferLen);
}
}
Fuzzer::~Fuzzer() { }
@ -457,10 +442,9 @@ void Fuzzer::ShuffleAndMinimize() {
bool Fuzzer::UpdateMaxCoverage() {
uintptr_t PrevPcBufferPos = MaxCoverage.PcBufferPos;
bool Res = CController->RecordMax(&MaxCoverage);
bool Res = RecordMaxCoverage(&MaxCoverage);
if (Options.PrintNewCovPcs && PrevPcBufferPos != MaxCoverage.PcBufferPos) {
uintptr_t* PcBuffer = CController->pc_buffer();
for (size_t I = PrevPcBufferPos; I < MaxCoverage.PcBufferPos; ++I) {
Printf("%p\n", PcBuffer[I]);
}
@ -473,7 +457,7 @@ bool Fuzzer::RunOne(const uint8_t *Data, size_t Size) {
TotalNumberOfRuns++;
// TODO(aizatsky): this Reset call seems to be not needed.
CController->ResetCounters();
ResetCounters();
ExecuteCallback(Data, Size);
bool Res = UpdateMaxCoverage();
@ -511,18 +495,19 @@ 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
// so that we reliably find buffer overflows in it.
std::unique_ptr<uint8_t[]> DataCopy(new uint8_t[Size]);
memcpy(DataCopy.get(), Data, Size);
uint8_t *DataCopy = new uint8_t[Size];
memcpy(DataCopy, Data, Size);
if (CurrentUnitData && CurrentUnitData != Data)
memcpy(CurrentUnitData, Data, Size);
AssignTaintLabels(DataCopy.get(), Size);
AssignTaintLabels(DataCopy, Size);
CurrentUnitSize = Size;
AllocTracer.Start();
int Res = CB(DataCopy.get(), Size);
int Res = CB(DataCopy, Size);
(void)Res;
HasMoreMallocsThanFrees = AllocTracer.Stop();
CurrentUnitSize = 0;
assert(Res == 0);
delete[] DataCopy;
}
std::string Fuzzer::Coverage::DebugString() const {
@ -728,9 +713,9 @@ size_t Fuzzer::ChooseUnitIdxToMutate() {
}
void Fuzzer::ResetCoverage() {
CController->Reset();
ResetEdgeCoverage();
MaxCoverage.Reset();
CController->Prepare(&MaxCoverage);
PrepareCounters(&MaxCoverage);
}
// Experimental search heuristic: drilling.