forked from OSchip/llvm-project
[libFuzzer] more refactoring around CurrentUnit. Also add a threading test on which we currently have a race (when reporting bugs from multiple threads)
llvm-svn: 270929
This commit is contained in:
parent
274cb1d224
commit
d8384122a3
|
@ -403,11 +403,7 @@ public:
|
|||
void ResetCoverage();
|
||||
|
||||
bool InFuzzingThread() const { return IsMyThread; }
|
||||
size_t GetCurrentUnitInFuzzingThead(const uint8_t **Data) const {
|
||||
assert(InFuzzingThread());
|
||||
*Data = CurrentUnitData;
|
||||
return CurrentUnitSize;
|
||||
}
|
||||
size_t GetCurrentUnitInFuzzingThead(const uint8_t **Data) const;
|
||||
|
||||
private:
|
||||
void AlarmCallback();
|
||||
|
@ -445,6 +441,8 @@ private:
|
|||
void DumpCurrentUnit(const char *Prefix);
|
||||
void DeathCallback();
|
||||
|
||||
void SetCurrentUnit(const uint8_t *Data, size_t Size);
|
||||
size_t GetCurrentUnitNoThreadCheck(const uint8_t **Data) const;
|
||||
const uint8_t *CurrentUnitData = nullptr;
|
||||
size_t CurrentUnitSize = 0;
|
||||
bool InOOMState = false;
|
||||
|
|
|
@ -170,20 +170,19 @@ void Fuzzer::StaticDeathCallback() {
|
|||
}
|
||||
|
||||
void Fuzzer::DumpCurrentUnit(const char *Prefix) {
|
||||
if (CurrentUnitSize <= kMaxUnitSizeToPrint) {
|
||||
PrintHexArray(CurrentUnitData, CurrentUnitSize, "\n");
|
||||
PrintASCII(CurrentUnitData, CurrentUnitSize, "\n");
|
||||
const uint8_t *UnitData;
|
||||
size_t UnitSize = GetCurrentUnitNoThreadCheck(&UnitData);
|
||||
if (UnitSize <= kMaxUnitSizeToPrint) {
|
||||
PrintHexArray(UnitData, UnitSize, "\n");
|
||||
PrintASCII(UnitData, UnitSize, "\n");
|
||||
}
|
||||
WriteUnitToFileWithPrefix(
|
||||
{CurrentUnitData, CurrentUnitData + CurrentUnitSize}, Prefix);
|
||||
{UnitData, UnitData + UnitSize}, Prefix);
|
||||
}
|
||||
|
||||
NO_SANITIZE_MEMORY
|
||||
void Fuzzer::DeathCallback() {
|
||||
if (CurrentUnitSize) {
|
||||
Printf("DEATH:\n");
|
||||
DumpCurrentUnit("crash-");
|
||||
}
|
||||
DumpCurrentUnit("crash-");
|
||||
PrintFinalStats();
|
||||
}
|
||||
|
||||
|
@ -224,11 +223,15 @@ void Fuzzer::InterruptCallback() {
|
|||
NO_SANITIZE_MEMORY
|
||||
void Fuzzer::AlarmCallback() {
|
||||
assert(Options.UnitTimeoutSec > 0);
|
||||
if (!InFuzzingThread()) return;
|
||||
const uint8_t *UnitData;
|
||||
size_t UnitSize = GetCurrentUnitInFuzzingThead(&UnitData);
|
||||
if (InOOMState) {
|
||||
Printf("==%d== ERROR: libFuzzer: out-of-memory (used: %zdMb; limit: %zdMb)\n",
|
||||
GetPid(), GetPeakRSSMb(), Options.RssLimitMb);
|
||||
Printf(
|
||||
"==%d== ERROR: libFuzzer: out-of-memory (used: %zdMb; limit: %zdMb)\n",
|
||||
GetPid(), GetPeakRSSMb(), Options.RssLimitMb);
|
||||
Printf(" To change the out-of-memory limit use -rss_limit_mb=<N>\n");
|
||||
if (CurrentUnitSize && CurrentUnitData) {
|
||||
if (UnitSize && UnitData) {
|
||||
DumpCurrentUnit("oom-");
|
||||
if (__sanitizer_print_stack_trace)
|
||||
__sanitizer_print_stack_trace();
|
||||
|
@ -238,7 +241,7 @@ void Fuzzer::AlarmCallback() {
|
|||
_Exit(Options.ErrorExitCode); // Stop right now.
|
||||
}
|
||||
|
||||
if (!CurrentUnitSize)
|
||||
if (!UnitSize)
|
||||
return; // We have not started running units yet.
|
||||
size_t Seconds =
|
||||
duration_cast<seconds>(system_clock::now() - UnitStartTime).count();
|
||||
|
@ -498,6 +501,22 @@ void __sanitizer_free_hook(void *ptr) {
|
|||
}
|
||||
} // extern "C"
|
||||
|
||||
void Fuzzer::SetCurrentUnit(const uint8_t *Data, size_t Size) {
|
||||
assert(InFuzzingThread());
|
||||
CurrentUnitSize = Size;
|
||||
CurrentUnitData = Data;
|
||||
}
|
||||
|
||||
size_t Fuzzer::GetCurrentUnitNoThreadCheck(const uint8_t **Data) const {
|
||||
*Data = CurrentUnitData;
|
||||
return CurrentUnitSize;
|
||||
}
|
||||
|
||||
size_t Fuzzer::GetCurrentUnitInFuzzingThead(const uint8_t **Data) const {
|
||||
assert(InFuzzingThread());
|
||||
return GetCurrentUnitNoThreadCheck(Data);
|
||||
}
|
||||
|
||||
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
|
||||
|
@ -505,14 +524,12 @@ void Fuzzer::ExecuteCallback(const uint8_t *Data, size_t Size) {
|
|||
std::unique_ptr<uint8_t[]> DataCopy(new uint8_t[Size]);
|
||||
memcpy(DataCopy.get(), Data, Size);
|
||||
AssignTaintLabels(DataCopy.get(), Size);
|
||||
CurrentUnitData = DataCopy.get();
|
||||
CurrentUnitSize = Size;
|
||||
SetCurrentUnit(DataCopy.get(), Size);
|
||||
AllocTracer.Start();
|
||||
int Res = CB(DataCopy.get(), Size);
|
||||
(void)Res;
|
||||
HasMoreMallocsThanFrees = AllocTracer.Stop();
|
||||
CurrentUnitSize = 0;
|
||||
CurrentUnitData = nullptr;
|
||||
SetCurrentUnit(nullptr, 0);
|
||||
assert(Res == 0);
|
||||
}
|
||||
|
||||
|
@ -672,8 +689,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");
|
||||
CurrentUnitData = Data;
|
||||
CurrentUnitSize = Size;
|
||||
SetCurrentUnit(Data, Size);
|
||||
DumpCurrentUnit("leak-");
|
||||
PrintFinalStats();
|
||||
_Exit(Options.ErrorExitCode); // not exit() to disable lsan further on.
|
||||
|
|
|
@ -58,6 +58,7 @@ set(Tests
|
|||
SimpleFnAdapterTest
|
||||
SimpleHashTest
|
||||
SimpleTest
|
||||
SimpleThreadedTest
|
||||
SpamyTest
|
||||
StrcmpTest
|
||||
StrncmpTest
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
|
||||
// Threaded test for a fuzzer. The fuzzer should find "H"
|
||||
#include <assert.h>
|
||||
#include <cstdint>
|
||||
#include <cstddef>
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
#include <thread>
|
||||
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
|
||||
auto C = [&] {
|
||||
if (Size >= 2 && Data[0] == 'H') {
|
||||
std::cout << "BINGO; Found the target, exiting\n";
|
||||
abort();
|
||||
}
|
||||
};
|
||||
std::thread T[] = {std::thread(C), std::thread(C), std::thread(C),
|
||||
std::thread(C), std::thread(C), std::thread(C)};
|
||||
for (auto &X : T)
|
||||
X.join();
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -3,7 +3,6 @@ LEAK_DURING: ERROR: LeakSanitizer: detected memory leaks
|
|||
LEAK_DURING: Direct leak of 4 byte(s) in 1 object(s) allocated from:
|
||||
LEAK_DURING-NOT: DONE
|
||||
LEAK_DURING-NOT: Done
|
||||
LEAK_DURING-NOT: DEATH:
|
||||
|
||||
RUN: not LLVMFuzzer-LeakTest -runs=0 -detect_leaks=1 %S 2>&1 | FileCheck %s --check-prefix=LEAK_IN_CORPUS
|
||||
LEAK_IN_CORPUS: ERROR: LeakSanitizer: detected memory leaks
|
||||
|
@ -14,7 +13,6 @@ RUN: not LLVMFuzzer-LeakTest -runs=100000 -detect_leaks=0 2>&1 | FileCheck %s --
|
|||
RUN: not LLVMFuzzer-LeakTest -runs=100000 2>&1 | FileCheck %s --check-prefix=LEAK_DURING
|
||||
LEAK_AFTER: Done 100000 runs in
|
||||
LEAK_AFTER: ERROR: LeakSanitizer: detected memory leaks
|
||||
LEAK_AFTER-NOT: DEATH:
|
||||
|
||||
RUN: not LLVMFuzzer-LeakTimeoutTest -timeout=1 2>&1 | FileCheck %s --check-prefix=LEAK_TIMEOUT
|
||||
LEAK_TIMEOUT: ERROR: libFuzzer: timeout after
|
||||
|
|
Loading…
Reference in New Issue