diff options
Diffstat (limited to 'llvm/lib')
-rw-r--r-- | llvm/lib/Fuzzer/FuzzerInternal.h | 8 | ||||
-rw-r--r-- | llvm/lib/Fuzzer/FuzzerLoop.cpp | 52 | ||||
-rw-r--r-- | llvm/lib/Fuzzer/test/CMakeLists.txt | 1 | ||||
-rw-r--r-- | llvm/lib/Fuzzer/test/SimpleThreadedTest.cpp | 25 | ||||
-rw-r--r-- | llvm/lib/Fuzzer/test/fuzzer-leak.test | 2 |
5 files changed, 63 insertions, 25 deletions
diff --git a/llvm/lib/Fuzzer/FuzzerInternal.h b/llvm/lib/Fuzzer/FuzzerInternal.h index e6bef799f13..c26aa5f4b21 100644 --- a/llvm/lib/Fuzzer/FuzzerInternal.h +++ b/llvm/lib/Fuzzer/FuzzerInternal.h @@ -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; diff --git a/llvm/lib/Fuzzer/FuzzerLoop.cpp b/llvm/lib/Fuzzer/FuzzerLoop.cpp index e38a29ab1fc..6aaa09fddc0 100644 --- a/llvm/lib/Fuzzer/FuzzerLoop.cpp +++ b/llvm/lib/Fuzzer/FuzzerLoop.cpp @@ -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. diff --git a/llvm/lib/Fuzzer/test/CMakeLists.txt b/llvm/lib/Fuzzer/test/CMakeLists.txt index 5703de804cf..5ff11b0669e 100644 --- a/llvm/lib/Fuzzer/test/CMakeLists.txt +++ b/llvm/lib/Fuzzer/test/CMakeLists.txt @@ -58,6 +58,7 @@ set(Tests SimpleFnAdapterTest SimpleHashTest SimpleTest + SimpleThreadedTest SpamyTest StrcmpTest StrncmpTest diff --git a/llvm/lib/Fuzzer/test/SimpleThreadedTest.cpp b/llvm/lib/Fuzzer/test/SimpleThreadedTest.cpp new file mode 100644 index 00000000000..5f02d3f8457 --- /dev/null +++ b/llvm/lib/Fuzzer/test/SimpleThreadedTest.cpp @@ -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; +} + diff --git a/llvm/lib/Fuzzer/test/fuzzer-leak.test b/llvm/lib/Fuzzer/test/fuzzer-leak.test index 184e199ff14..61410aae401 100644 --- a/llvm/lib/Fuzzer/test/fuzzer-leak.test +++ b/llvm/lib/Fuzzer/test/fuzzer-leak.test @@ -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 |