diff options
Diffstat (limited to 'llvm')
-rw-r--r-- | llvm/lib/Fuzzer/CMakeLists.txt | 1 | ||||
-rw-r--r-- | llvm/lib/Fuzzer/FuzzerInternal.h | 10 | ||||
-rw-r--r-- | llvm/lib/Fuzzer/FuzzerLoop.cpp | 4 | ||||
-rw-r--r-- | llvm/lib/Fuzzer/FuzzerMutate.cpp | 6 | ||||
-rw-r--r-- | llvm/lib/Fuzzer/FuzzerTracePC.cpp | 23 | ||||
-rw-r--r-- | llvm/lib/Fuzzer/FuzzerTracePC.h | 23 | ||||
-rw-r--r-- | llvm/lib/Fuzzer/FuzzerTraceState.cpp | 112 | ||||
-rw-r--r-- | llvm/lib/Fuzzer/FuzzerUtil.cpp | 7 | ||||
-rw-r--r-- | llvm/lib/Fuzzer/FuzzerUtil.h | 2 | ||||
-rw-r--r-- | llvm/lib/Fuzzer/test/fuzzer-traces-hooks.test | 2 |
10 files changed, 61 insertions, 129 deletions
diff --git a/llvm/lib/Fuzzer/CMakeLists.txt b/llvm/lib/Fuzzer/CMakeLists.txt index fa743c280e8..bc744890b99 100644 --- a/llvm/lib/Fuzzer/CMakeLists.txt +++ b/llvm/lib/Fuzzer/CMakeLists.txt @@ -46,7 +46,6 @@ if ( LLVM_USE_SANITIZE_COVERAGE OR CMAKE_SYSTEM_NAME MATCHES "Darwin|Linux" ) FuzzerShmemPosix.cpp FuzzerShmemWindows.cpp FuzzerTracePC.cpp - FuzzerTraceState.cpp FuzzerUtil.cpp FuzzerUtilDarwin.cpp FuzzerUtilLinux.cpp diff --git a/llvm/lib/Fuzzer/FuzzerInternal.h b/llvm/lib/Fuzzer/FuzzerInternal.h index a732f895375..549ebc0a3c3 100644 --- a/llvm/lib/Fuzzer/FuzzerInternal.h +++ b/llvm/lib/Fuzzer/FuzzerInternal.h @@ -38,7 +38,6 @@ public: void Loop(); void MinimizeCrashLoop(const Unit &U); void ShuffleAndMinimize(UnitVector *V); - void InitializeTraceState(); void RereadOutputCorpus(size_t MaxSize); size_t secondsSinceProcessStartUp() { @@ -104,15 +103,6 @@ private: void ShuffleCorpus(UnitVector *V); void CheckExitOnSrcPosOrItem(); - // Trace-based fuzzing: we run a unit with some kind of tracing - // enabled and record potentially useful mutations. Then - // We apply these mutations one by one to the unit and run it again. - - // Start tracing; forget all previously proposed mutations. - void StartTraceRecording(); - // Stop tracing. - void StopTraceRecording(); - static void StaticDeathCallback(); void DumpCurrentUnit(const char *Prefix); void DeathCallback(); diff --git a/llvm/lib/Fuzzer/FuzzerLoop.cpp b/llvm/lib/Fuzzer/FuzzerLoop.cpp index 6816f3af8a6..1693cd078a9 100644 --- a/llvm/lib/Fuzzer/FuzzerLoop.cpp +++ b/llvm/lib/Fuzzer/FuzzerLoop.cpp @@ -114,7 +114,6 @@ Fuzzer::Fuzzer(UserCallback CB, InputCorpus &Corpus, MutationDispatcher &MD, : CB(CB), Corpus(Corpus), MD(MD), Options(Options) { if (EF->__sanitizer_set_death_callback) EF->__sanitizer_set_death_callback(StaticDeathCallback); - InitializeTraceState(); assert(!F); F = this; TPC.ResetMaps(); @@ -600,13 +599,10 @@ void Fuzzer::MutateAndTestOne() { assert(NewSize > 0 && "Mutator returned empty unit"); assert(NewSize <= CurrentMaxMutationLen && "Mutator return overisized unit"); Size = NewSize; - if (i == 0) - StartTraceRecording(); II.NumExecutedMutations++; if (RunOne(CurrentUnitData, Size, /*MayDeleteFile=*/true, &II)) ReportNewCoverage(&II, {CurrentUnitData, CurrentUnitData + Size}); - StopTraceRecording(); TryDetectingAMemoryLeak(CurrentUnitData, Size, /*DuringInitialCorpusExecution*/ false); } diff --git a/llvm/lib/Fuzzer/FuzzerMutate.cpp b/llvm/lib/Fuzzer/FuzzerMutate.cpp index 53cb9027e45..bc2cf2c1bdb 100644 --- a/llvm/lib/Fuzzer/FuzzerMutate.cpp +++ b/llvm/lib/Fuzzer/FuzzerMutate.cpp @@ -251,7 +251,7 @@ size_t MutationDispatcher::Mutate_AddWordFromTORC( uint8_t *Data, size_t Size, size_t MaxSize) { Word W; DictionaryEntry DE; - switch (Rand(3)) { + switch (Rand(4)) { case 0: { auto X = TPC.TORC8.Get(Rand.Rand()); DE = MakeDictionaryEntryFromCMP(X.A, X.B, Data, Size); @@ -267,6 +267,10 @@ size_t MutationDispatcher::Mutate_AddWordFromTORC( auto X = TPC.TORCW.Get(Rand.Rand()); DE = MakeDictionaryEntryFromCMP(X.A, X.B, Data, Size); } break; + case 3: if (Options.UseMemmem) { + auto X = TPC.MMT.Get(Rand.Rand()); + DE = DictionaryEntry(X); + } break; default: assert(0); } diff --git a/llvm/lib/Fuzzer/FuzzerTracePC.cpp b/llvm/lib/Fuzzer/FuzzerTracePC.cpp index 909227ea7e0..ced0a213334 100644 --- a/llvm/lib/Fuzzer/FuzzerTracePC.cpp +++ b/llvm/lib/Fuzzer/FuzzerTracePC.cpp @@ -37,6 +37,8 @@ namespace fuzzer { TracePC TPC; +int ScopedDoingMyOwnMemOrStr::DoingMyOwnMemOrStr; + uint8_t *TracePC::Counters() const { return __sancov_trace_pc_guard_8bit_counters; } @@ -475,4 +477,25 @@ void __sanitizer_weak_hook_strcasecmp(void *called_pc, const char *s1, if (fuzzer::ScopedDoingMyOwnMemOrStr::DoingMyOwnMemOrStr) return; return __sanitizer_weak_hook_strcmp(called_pc, s1, s2, result); } + +ATTRIBUTE_INTERFACE ATTRIBUTE_NO_SANITIZE_MEMORY +void __sanitizer_weak_hook_strstr(void *called_pc, const char *s1, + const char *s2, char *result) { + if (fuzzer::ScopedDoingMyOwnMemOrStr::DoingMyOwnMemOrStr) return; + fuzzer::TPC.MMT.Add(reinterpret_cast<const uint8_t *>(s2), strlen(s2)); +} + +ATTRIBUTE_INTERFACE ATTRIBUTE_NO_SANITIZE_MEMORY +void __sanitizer_weak_hook_strcasestr(void *called_pc, const char *s1, + const char *s2, char *result) { + if (fuzzer::ScopedDoingMyOwnMemOrStr::DoingMyOwnMemOrStr) return; + fuzzer::TPC.MMT.Add(reinterpret_cast<const uint8_t *>(s2), strlen(s2)); +} + +ATTRIBUTE_INTERFACE ATTRIBUTE_NO_SANITIZE_MEMORY +void __sanitizer_weak_hook_memmem(void *called_pc, const void *s1, size_t len1, + const void *s2, size_t len2, void *result) { + if (fuzzer::ScopedDoingMyOwnMemOrStr::DoingMyOwnMemOrStr) return; + fuzzer::TPC.MMT.Add(reinterpret_cast<const uint8_t *>(s2), len2); +} } // extern "C" diff --git a/llvm/lib/Fuzzer/FuzzerTracePC.h b/llvm/lib/Fuzzer/FuzzerTracePC.h index 5ec8c590b4d..b36c4f54306 100644 --- a/llvm/lib/Fuzzer/FuzzerTracePC.h +++ b/llvm/lib/Fuzzer/FuzzerTracePC.h @@ -45,6 +45,28 @@ struct TableOfRecentCompares { Pair Table[kSize]; }; +template <size_t kSizeT> +struct MemMemTable { + static const size_t kSize = kSizeT; + Word MemMemWords[kSize]; + Word EmptyWord; + + void Add(const uint8_t *Data, size_t Size) { + if (Size <= 2) return; + Size = std::min(Size, Word::GetMaxSize()); + size_t Idx = SimpleFastHash(Data, Size) % kSize; + MemMemWords[Idx].Set(Data, Size); + } + const Word &Get(size_t Idx) { + for (size_t i = 0; i < kSize; i++) { + const Word &W = MemMemWords[(Idx + i) % kSize]; + if (W.size()) return W; + } + EmptyWord.Set(nullptr, 0); + return EmptyWord; + } +}; + class TracePC { public: static const size_t kNumPCs = 1 << 21; @@ -81,6 +103,7 @@ class TracePC { TableOfRecentCompares<uint32_t, 32> TORC4; TableOfRecentCompares<uint64_t, 32> TORC8; TableOfRecentCompares<Word, 32> TORCW; + MemMemTable<1024> MMT; void PrintNewPCs(); void InitializePrintNewPCs(); diff --git a/llvm/lib/Fuzzer/FuzzerTraceState.cpp b/llvm/lib/Fuzzer/FuzzerTraceState.cpp deleted file mode 100644 index 101ab485c4e..00000000000 --- a/llvm/lib/Fuzzer/FuzzerTraceState.cpp +++ /dev/null @@ -1,112 +0,0 @@ -//===- FuzzerTraceState.cpp - Trace-based fuzzer mutator ------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// Data tracing. -//===----------------------------------------------------------------------===// - -#include "FuzzerDictionary.h" -#include "FuzzerIO.h" -#include "FuzzerInternal.h" -#include "FuzzerMutate.h" -#include "FuzzerTracePC.h" -#include <algorithm> -#include <cstring> -#include <map> -#include <set> -#include <thread> - -namespace fuzzer { - -// Declared as static globals for faster checks inside the hooks. -static bool RecordingMemmem = false; - -int ScopedDoingMyOwnMemOrStr::DoingMyOwnMemOrStr; - -class TraceState { -public: - TraceState(MutationDispatcher &MD, const FuzzingOptions &Options, - const Fuzzer *F) - : MD(MD), Options(Options), F(F) {} - - void StartTraceRecording() { - if (!Options.UseMemmem) - return; - RecordingMemmem = true; - InterestingWords.clear(); - MD.ClearAutoDictionary(); - } - - void StopTraceRecording() { - if (!RecordingMemmem) - return; - for (auto &W : InterestingWords) - MD.AddWordToAutoDictionary({W}); - } - - void AddInterestingWord(const uint8_t *Data, size_t Size) { - if (!RecordingMemmem || !F->InFuzzingThread()) return; - if (Size <= 1) return; - Size = std::min(Size, Word::GetMaxSize()); - Word W(Data, Size); - InterestingWords.insert(W); - } - - private: - - // TODO: std::set is too inefficient, need to have a custom DS here. - std::set<Word> InterestingWords; - MutationDispatcher &MD; - const FuzzingOptions Options; - const Fuzzer *F; -}; - -static TraceState *TS; - -void Fuzzer::StartTraceRecording() { - if (!TS) return; - TS->StartTraceRecording(); -} - -void Fuzzer::StopTraceRecording() { - if (!TS) return; - TS->StopTraceRecording(); -} - -void Fuzzer::InitializeTraceState() { - if (!Options.UseMemmem) return; - TS = new TraceState(MD, Options, this); -} - -} // namespace fuzzer - -using fuzzer::TS; - -extern "C" { - -ATTRIBUTE_INTERFACE ATTRIBUTE_NO_SANITIZE_MEMORY -void __sanitizer_weak_hook_strstr(void *called_pc, const char *s1, - const char *s2, char *result) { - if (fuzzer::ScopedDoingMyOwnMemOrStr::DoingMyOwnMemOrStr) return; - TS->AddInterestingWord(reinterpret_cast<const uint8_t *>(s2), strlen(s2)); -} - -ATTRIBUTE_INTERFACE ATTRIBUTE_NO_SANITIZE_MEMORY -void __sanitizer_weak_hook_strcasestr(void *called_pc, const char *s1, - const char *s2, char *result) { - if (fuzzer::ScopedDoingMyOwnMemOrStr::DoingMyOwnMemOrStr) return; - TS->AddInterestingWord(reinterpret_cast<const uint8_t *>(s2), strlen(s2)); -} - -ATTRIBUTE_INTERFACE ATTRIBUTE_NO_SANITIZE_MEMORY -void __sanitizer_weak_hook_memmem(void *called_pc, const void *s1, size_t len1, - const void *s2, size_t len2, void *result) { - if (fuzzer::ScopedDoingMyOwnMemOrStr::DoingMyOwnMemOrStr) return; - TS->AddInterestingWord(reinterpret_cast<const uint8_t *>(s2), len2); -} - -} // extern "C" diff --git a/llvm/lib/Fuzzer/FuzzerUtil.cpp b/llvm/lib/Fuzzer/FuzzerUtil.cpp index f5fd3a85187..2d95f40e46a 100644 --- a/llvm/lib/Fuzzer/FuzzerUtil.cpp +++ b/llvm/lib/Fuzzer/FuzzerUtil.cpp @@ -215,4 +215,11 @@ bool ExecuteCommandAndReadOutput(const std::string &Command, std::string *Out) { return true; } +size_t SimpleFastHash(const uint8_t *Data, size_t Size) { + size_t Res = 0; + for (size_t i = 0; i < Size; i++) + Res = Res * 11 + Data[i]; + return Res; +} + } // namespace fuzzer diff --git a/llvm/lib/Fuzzer/FuzzerUtil.h b/llvm/lib/Fuzzer/FuzzerUtil.h index f84fd9ef0fc..c9fb1c12e08 100644 --- a/llvm/lib/Fuzzer/FuzzerUtil.h +++ b/llvm/lib/Fuzzer/FuzzerUtil.h @@ -71,6 +71,8 @@ std::string DisassembleCmd(const std::string &FileName); std::string SearchRegexCmd(const std::string &Regex); +size_t SimpleFastHash(const uint8_t *Data, size_t Size); + } // namespace fuzzer #endif // LLVM_FUZZER_UTIL_H diff --git a/llvm/lib/Fuzzer/test/fuzzer-traces-hooks.test b/llvm/lib/Fuzzer/test/fuzzer-traces-hooks.test index f93a8b7199e..77ca4b47bd0 100644 --- a/llvm/lib/Fuzzer/test/fuzzer-traces-hooks.test +++ b/llvm/lib/Fuzzer/test/fuzzer-traces-hooks.test @@ -10,7 +10,7 @@ RUN: not LLVMFuzzer-StrstrTest -seed=1 -runs=2000000 2>&1 | File RUN: not LLVMFuzzer-Memcmp64BytesTest -seed=1 -runs=1000000 2>&1 | FileCheck %s -RUN: LLVMFuzzer-RepeatedMemcmp -seed=11 -runs=100000 2>&1 | FileCheck %s --check-prefix=RECOMMENDED_DICT +RUN: LLVMFuzzer-RepeatedMemcmp -seed=11 -runs=100000 -max_len=20 2>&1 | FileCheck %s --check-prefix=RECOMMENDED_DICT RECOMMENDED_DICT:###### Recommended dictionary. ###### RECOMMENDED_DICT-DAG: "foo" RECOMMENDED_DICT-DAG: "bar" |