1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-19 02:52:53 +02:00

[libFuzzer] more refactoring: make sure CurrentUnitData is awlays a valid pointer to read from

llvm-svn: 270942
This commit is contained in:
Kostya Serebryany 2016-05-27 00:21:33 +00:00
parent 2377837e57
commit becd6c1393
3 changed files with 26 additions and 15 deletions

View File

@ -441,9 +441,10 @@ private:
void DumpCurrentUnit(const char *Prefix);
void DeathCallback();
void SetCurrentUnit(const uint8_t *Data, size_t Size);
void SetCurrentUnit(size_t Size);
size_t GetCurrentUnitNoThreadCheck(const uint8_t **Data) const;
const uint8_t *CurrentUnitData = nullptr;
void LazyAllocateCurrentUnitData();
uint8_t *CurrentUnitData = nullptr;
size_t CurrentUnitSize = 0;
bool InOOMState = false;
@ -455,7 +456,6 @@ private:
std::vector<Unit> Corpus;
std::unordered_set<std::string> UnitHashesAddedToCorpus;
std::vector<uint8_t> MutateInPlaceHere;
std::piecewise_constant_distribution<double> CorpusDistribution;
UserCallback CB;

View File

@ -159,6 +159,11 @@ Fuzzer::Fuzzer(UserCallback CB, MutationDispatcher &MD, FuzzingOptions Options)
IsMyThread = true;
}
void Fuzzer::LazyAllocateCurrentUnitData() {
if (CurrentUnitData || Options.MaxLen == 0) return;
CurrentUnitData = new uint8_t[Options.MaxLen];
}
void Fuzzer::SetDeathCallback() {
CHECK_WEAK_API_FUNCTION(__sanitizer_set_death_callback);
__sanitizer_set_death_callback(StaticDeathCallback);
@ -501,10 +506,9 @@ void __sanitizer_free_hook(void *ptr) {
}
} // extern "C"
void Fuzzer::SetCurrentUnit(const uint8_t *Data, size_t Size) {
void Fuzzer::SetCurrentUnit(size_t Size) {
assert(InFuzzingThread());
CurrentUnitSize = Size;
CurrentUnitData = Data;
}
size_t Fuzzer::GetCurrentUnitNoThreadCheck(const uint8_t **Data) const {
@ -518,18 +522,21 @@ size_t Fuzzer::GetCurrentUnitInFuzzingThead(const uint8_t **Data) const {
}
void Fuzzer::ExecuteCallback(const uint8_t *Data, size_t Size) {
LazyAllocateCurrentUnitData();
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);
if (CurrentUnitData && CurrentUnitData != Data)
memcpy(CurrentUnitData, Data, Size);
AssignTaintLabels(DataCopy.get(), Size);
SetCurrentUnit(DataCopy.get(), Size);
SetCurrentUnit(Size);
AllocTracer.Start();
int Res = CB(DataCopy.get(), Size);
(void)Res;
HasMoreMallocsThanFrees = AllocTracer.Stop();
SetCurrentUnit(nullptr, 0);
SetCurrentUnit(0);
assert(Res == 0);
}
@ -689,7 +696,7 @@ void Fuzzer::TryDetectingAMemoryLeak(const uint8_t *Data, size_t Size,
if (DuringInitialCorpusExecution)
Printf("\nINFO: a leak has been found in the initial corpus.\n\n");
Printf("INFO: to ignore leaks on libFuzzer side use -detect_leaks=0.\n\n");
SetCurrentUnit(Data, Size);
SetCurrentUnit(Size);
DumpCurrentUnit("leak-");
PrintFinalStats();
_Exit(Options.ErrorExitCode); // not exit() to disable lsan further on.
@ -697,32 +704,33 @@ void Fuzzer::TryDetectingAMemoryLeak(const uint8_t *Data, size_t Size,
}
void Fuzzer::MutateAndTestOne() {
LazyAllocateCurrentUnitData();
MD.StartMutationSequence();
auto &U = ChooseUnitToMutate();
MutateInPlaceHere.resize(Options.MaxLen);
assert(CurrentUnitData);
size_t Size = U.size();
assert(Size <= Options.MaxLen && "Oversized Unit");
memcpy(MutateInPlaceHere.data(), U.data(), Size);
memcpy(CurrentUnitData, U.data(), Size);
for (int i = 0; i < Options.MutateDepth; i++) {
size_t NewSize = 0;
if (LLVMFuzzerCustomMutator)
NewSize = LLVMFuzzerCustomMutator(MutateInPlaceHere.data(), Size,
NewSize = LLVMFuzzerCustomMutator(CurrentUnitData, Size,
Options.MaxLen, MD.GetRand().Rand());
else
NewSize = MD.Mutate(MutateInPlaceHere.data(), Size, Options.MaxLen);
NewSize = MD.Mutate(CurrentUnitData, Size, Options.MaxLen);
assert(NewSize > 0 && "Mutator returned empty unit");
assert(NewSize <= Options.MaxLen &&
"Mutator return overisized unit");
Size = NewSize;
if (Options.OnlyASCII)
ToASCII(MutateInPlaceHere.data(), Size);
ToASCII(CurrentUnitData, Size);
if (i == 0)
StartTraceRecording();
RunOneAndUpdateCorpus(MutateInPlaceHere.data(), Size);
RunOneAndUpdateCorpus(CurrentUnitData, Size);
StopTraceRecording();
TryDetectingAMemoryLeak(MutateInPlaceHere.data(), Size,
TryDetectingAMemoryLeak(CurrentUnitData, Size,
/*DuringInitialCorpusExecution*/ false);
}
}

View File

@ -14,6 +14,9 @@ RUN: not LLVMFuzzer-LeakTest -runs=100000 2>&1 | FileCheck %s --
LEAK_AFTER: Done 100000 runs in
LEAK_AFTER: ERROR: LeakSanitizer: detected memory leaks
RUN: not LLVMFuzzer-LeakTest -runs=100000 -max_len=1 2>&1 | FileCheck %s --check-prefix=MAX_LEN_1
MAX_LEN_1: Test unit written to ./leak-7cf184f4c67ad58283ecb19349720b0cae756829
RUN: not LLVMFuzzer-LeakTimeoutTest -timeout=1 2>&1 | FileCheck %s --check-prefix=LEAK_TIMEOUT
LEAK_TIMEOUT: ERROR: libFuzzer: timeout after
LEAK_TIMEOUT-NOT: LeakSanitizer