From 7ec0c56e07eb9fa7b571274214e2452c33adaabc Mon Sep 17 00:00:00 2001 From: Kostya Serebryany Date: Sat, 13 Feb 2016 03:25:16 +0000 Subject: [PATCH] [libFuzzer] get rid of UserSuppliedFuzzer; NFC llvm-svn: 260798 --- llvm/lib/Fuzzer/FuzzerDriver.cpp | 6 ++-- llvm/lib/Fuzzer/FuzzerInterface.cpp | 25 ---------------- llvm/lib/Fuzzer/FuzzerInternal.h | 52 ++++----------------------------- llvm/lib/Fuzzer/FuzzerLoop.cpp | 27 ++++++++--------- llvm/lib/Fuzzer/FuzzerMutate.cpp | 7 +++++ llvm/lib/Fuzzer/FuzzerTraceState.cpp | 14 ++++----- llvm/lib/Fuzzer/test/FuzzerUnittest.cpp | 4 +-- llvm/lib/Fuzzer/test/fuzzer-dfsan.test | 2 +- llvm/lib/Fuzzer/test/fuzzer.test | 1 + 9 files changed, 41 insertions(+), 97 deletions(-) diff --git a/llvm/lib/Fuzzer/FuzzerDriver.cpp b/llvm/lib/Fuzzer/FuzzerDriver.cpp index c606333..16a1470 100644 --- a/llvm/lib/Fuzzer/FuzzerDriver.cpp +++ b/llvm/lib/Fuzzer/FuzzerDriver.cpp @@ -315,12 +315,12 @@ int FuzzerDriver(const std::vector &Args, UserCallback Callback) { Printf("Seed: %u\n", Seed); Random Rand(Seed); - SimpleUserSuppliedFuzzer USF(&Rand, Callback); - Fuzzer F(USF, Options); + MutationDispatcher MD(Rand); + Fuzzer F(Callback, MD, Options); for (auto &U: Dictionary) if (U.size() <= Word::GetMaxSize()) - USF.GetMD().AddWordToManualDictionary(Word(U.data(), U.size())); + MD.AddWordToManualDictionary(Word(U.data(), U.size())); // Timer if (Flags.timeout > 0) diff --git a/llvm/lib/Fuzzer/FuzzerInterface.cpp b/llvm/lib/Fuzzer/FuzzerInterface.cpp index 9cb9161..5de7d61 100644 --- a/llvm/lib/Fuzzer/FuzzerInterface.cpp +++ b/llvm/lib/Fuzzer/FuzzerInterface.cpp @@ -16,30 +16,5 @@ namespace fuzzer { -UserSuppliedFuzzer::UserSuppliedFuzzer(Random *Rand) - : Rand(Rand), MD(new MutationDispatcher(*Rand)) {} - -UserSuppliedFuzzer::~UserSuppliedFuzzer() { - if (OwnRand) - delete Rand; - delete MD; -} - -size_t UserSuppliedFuzzer::Mutate(uint8_t *Data, size_t Size, size_t MaxSize) { - return GetMD().Mutate(Data, Size, MaxSize); -} - -size_t UserSuppliedFuzzer::CrossOver(const uint8_t *Data1, size_t Size1, - const uint8_t *Data2, size_t Size2, - uint8_t *Out, size_t MaxOutSize) { - return GetMD().CrossOver(Data1, Size1, Data2, Size2, Out, MaxOutSize); -} - - -size_t Mutate(uint8_t *Data, size_t Size, size_t MaxSize, unsigned int Seed) { - Random R(Seed); - MutationDispatcher MD(R); - return MD.Mutate(Data, Size, MaxSize); -} } // namespace fuzzer. diff --git a/llvm/lib/Fuzzer/FuzzerInternal.h b/llvm/lib/Fuzzer/FuzzerInternal.h index c966b26..5db6059 100644 --- a/llvm/lib/Fuzzer/FuzzerInternal.h +++ b/llvm/lib/Fuzzer/FuzzerInternal.h @@ -104,6 +104,7 @@ class Random { size_t Rand() { return R(); } size_t RandBool() { return Rand() % 2; } size_t operator()(size_t n) { return n ? Rand() % n : 0; } + std::mt19937 &Get_mt19937() { return R; } private: std::mt19937 R; }; @@ -173,37 +174,14 @@ public: void SetCorpus(const std::vector *Corpus); + Random &GetRand() { return Rand; } + private: Random &Rand; struct Impl; Impl *MDImpl; }; -class UserSuppliedFuzzer { - public: - UserSuppliedFuzzer(Random *Rand); - /// Executes the target function on 'Size' bytes of 'Data'. - virtual int TargetFunction(const uint8_t *Data, size_t Size) = 0; - /// Mutates 'Size' bytes of data in 'Data' inplace into up to 'MaxSize' bytes, - /// returns the new size of the data, which should be positive. - virtual size_t Mutate(uint8_t *Data, size_t Size, size_t MaxSize); - /// Crosses 'Data1' and 'Data2', writes up to 'MaxOutSize' bytes into Out, - /// returns the number of bytes written, which should be positive. - virtual size_t CrossOver(const uint8_t *Data1, size_t Size1, - const uint8_t *Data2, size_t Size2, - uint8_t *Out, size_t MaxOutSize); - virtual ~UserSuppliedFuzzer(); - - Random &GetRand() { return *Rand; } - - MutationDispatcher &GetMD() { return *MD; } - - private: - bool OwnRand = false; - Random *Rand; - MutationDispatcher *MD; -}; - class Fuzzer { public: struct FuzzingOptions { @@ -237,7 +215,7 @@ public: bool OutputCSV = false; bool PrintNewCovPcs = false; }; - Fuzzer(UserSuppliedFuzzer &USF, FuzzingOptions Options); + Fuzzer(UserCallback CB, MutationDispatcher &MD, FuzzingOptions Options); void AddToCorpus(const Unit &U) { Corpus.push_back(U); UpdateCorpusDistribution(); @@ -324,14 +302,9 @@ private: return Res; } - // TODO(krasin): remove GetRand from UserSuppliedFuzzer, - // and fully rely on the generator and the seed. - // The user supplied fuzzer will have a way to access the - // generator for its own purposes (like seeding the custom - // PRNG). - std::mt19937 Generator; std::piecewise_constant_distribution CorpusDistribution; - UserSuppliedFuzzer &USF; + UserCallback CB; + MutationDispatcher &MD; FuzzingOptions Options; system_clock::time_point ProcessStartTime = system_clock::now(); system_clock::time_point LastExternalSync = system_clock::now(); @@ -343,19 +316,6 @@ private: size_t LastCoveragePcBufferLen = 0; }; -class SimpleUserSuppliedFuzzer : public UserSuppliedFuzzer { -public: - SimpleUserSuppliedFuzzer(Random *Rand, UserCallback Callback) - : UserSuppliedFuzzer(Rand), Callback(Callback) {} - - virtual int TargetFunction(const uint8_t *Data, size_t Size) override { - return Callback(Data, Size); - } - -private: - UserCallback Callback = nullptr; -}; - }; // namespace fuzzer #endif // LLVM_FUZZER_INTERNAL_H diff --git a/llvm/lib/Fuzzer/FuzzerLoop.cpp b/llvm/lib/Fuzzer/FuzzerLoop.cpp index db542b2..1c2c369 100644 --- a/llvm/lib/Fuzzer/FuzzerLoop.cpp +++ b/llvm/lib/Fuzzer/FuzzerLoop.cpp @@ -60,8 +60,8 @@ static void MissingWeakApiFunction(const char *FnName) { // Only one Fuzzer per process. static Fuzzer *F; -Fuzzer::Fuzzer(UserSuppliedFuzzer &USF, FuzzingOptions Options) - : Generator(USF.GetRand().Rand()), USF(USF), Options(Options) { +Fuzzer::Fuzzer(UserCallback CB, MutationDispatcher &MD, FuzzingOptions Options) + : CB(CB), MD(MD), Options(Options) { SetDeathCallback(); InitializeTraceState(); assert(!F); @@ -184,13 +184,13 @@ void Fuzzer::RereadOutputCorpus() { void Fuzzer::ShuffleAndMinimize() { bool PreferSmall = (Options.PreferSmallDuringInitialShuffle == 1 || (Options.PreferSmallDuringInitialShuffle == -1 && - USF.GetRand().RandBool())); + MD.GetRand().RandBool())); if (Options.Verbosity) Printf("PreferSmall: %d\n", PreferSmall); PrintStats("READ "); std::vector NewCorpus; if (Options.ShuffleAtStartUp) { - std::random_shuffle(Corpus.begin(), Corpus.end(), USF.GetRand()); + std::random_shuffle(Corpus.begin(), Corpus.end(), MD.GetRand()); if (PreferSmall) std::stable_sort( Corpus.begin(), Corpus.end(), @@ -258,7 +258,7 @@ void Fuzzer::ExecuteCallback(const Unit &U) { AssignTaintLabels(Data.get(), U.size()); CurrentUnitData = Data.get(); CurrentUnitSize = U.size(); - int Res = USF.TargetFunction(Data.get(), U.size()); + int Res = CB(Data.get(), U.size()); (void)Res; assert(Res == 0); CurrentUnitData = nullptr; @@ -355,7 +355,7 @@ void Fuzzer::PrintStatusForNewUnit(const Unit &U) { PrintStats("NEW ", ""); if (Options.Verbosity) { Printf(" L: %zd ", U.size()); - USF.GetMD().PrintMutationSequence(); + MD.PrintMutationSequence(); Printf("\n"); } } @@ -364,7 +364,7 @@ void Fuzzer::ReportNewCoverage(const Unit &U) { Corpus.push_back(U); UpdateCorpusDistribution(); UnitHashesAddedToCorpus.insert(Hash(U)); - USF.GetMD().RecordSuccessfulMutationSequence(); + MD.RecordSuccessfulMutationSequence(); PrintStatusForNewUnit(U); WriteToOutputCorpus(U); if (Options.ExitOnFirst) @@ -404,7 +404,7 @@ void Fuzzer::Merge(const std::vector &Corpora) { } void Fuzzer::MutateAndTestOne() { - USF.GetMD().StartMutationSequence(); + MD.StartMutationSequence(); auto U = ChooseUnitToMutate(); @@ -414,9 +414,9 @@ void Fuzzer::MutateAndTestOne() { size_t NewSize = 0; if (LLVMFuzzerCustomMutator) NewSize = LLVMFuzzerCustomMutator(U.data(), Size, U.size(), - USF.GetRand().Rand()); + MD.GetRand().Rand()); else - NewSize = USF.Mutate(U.data(), Size, U.size()); + NewSize = MD.Mutate(U.data(), Size, U.size()); assert(NewSize > 0 && "Mutator returned empty unit"); assert(NewSize <= (size_t)Options.MaxLen && "Mutator return overisized unit"); @@ -432,7 +432,8 @@ void Fuzzer::MutateAndTestOne() { // Hypothesis: units added to the corpus last are more likely to be interesting. // This function gives more weight to the more recent units. size_t Fuzzer::ChooseUnitIdxToMutate() { - size_t Idx = static_cast(CorpusDistribution(Generator)); + size_t Idx = + static_cast(CorpusDistribution(MD.GetRand().Get_mt19937())); assert(Idx < Corpus.size()); return Idx; } @@ -489,7 +490,7 @@ void Fuzzer::Drill() { void Fuzzer::Loop() { system_clock::time_point LastCorpusReload = system_clock::now(); if (Options.DoCrossOver) - USF.GetMD().SetCorpus(&Corpus); + MD.SetCorpus(&Corpus); while (true) { SyncCorpus(); auto Now = system_clock::now(); @@ -508,7 +509,7 @@ void Fuzzer::Loop() { } PrintStats("DONE ", "\n"); - USF.GetMD().PrintRecommendedDictionary(); + MD.PrintRecommendedDictionary(); } void Fuzzer::SyncCorpus() { diff --git a/llvm/lib/Fuzzer/FuzzerMutate.cpp b/llvm/lib/Fuzzer/FuzzerMutate.cpp index eed2881..d5eece6 100644 --- a/llvm/lib/Fuzzer/FuzzerMutate.cpp +++ b/llvm/lib/Fuzzer/FuzzerMutate.cpp @@ -76,6 +76,7 @@ private: const size_t Dictionary::kMaxDictSize; + struct MutationDispatcher::Impl { // Dictionary provided by the user via -dict=DICT_FILE. Dictionary ManualDictionary; @@ -113,6 +114,12 @@ struct MutationDispatcher::Impl { size_t MaxSize); }; +size_t Mutate(uint8_t *Data, size_t Size, size_t MaxSize, unsigned int Seed) { + Random R(Seed); + MutationDispatcher MD(R); + return MD.Mutate(Data, Size, MaxSize); +} + static char FlipRandomBit(char X, Random &Rand) { int Bit = Rand(8); char Mask = 1 << Bit; diff --git a/llvm/lib/Fuzzer/FuzzerTraceState.cpp b/llvm/lib/Fuzzer/FuzzerTraceState.cpp index e41a84d..d996368 100644 --- a/llvm/lib/Fuzzer/FuzzerTraceState.cpp +++ b/llvm/lib/Fuzzer/FuzzerTraceState.cpp @@ -174,9 +174,9 @@ static bool RecordingMemcmp = false; class TraceState { public: - TraceState(UserSuppliedFuzzer &USF, const Fuzzer::FuzzingOptions &Options, + TraceState(MutationDispatcher &MD, const Fuzzer::FuzzingOptions &Options, uint8_t **CurrentUnitData, size_t *CurrentUnitSize) - : USF(USF), Options(Options), CurrentUnitData(CurrentUnitData), + : MD(MD), Options(Options), CurrentUnitData(CurrentUnitData), CurrentUnitSize(CurrentUnitSize) { // Current trace collection is not thread-friendly and it probably // does not have to be such, but at least we should not crash in presence @@ -210,7 +210,7 @@ class TraceState { RecordingTraces = Options.UseTraces; RecordingMemcmp = Options.UseMemcmp; NumMutations = 0; - USF.GetMD().ClearAutoDictionary(); + MD.ClearAutoDictionary(); } void StopTraceRecording() { @@ -237,7 +237,7 @@ class TraceState { } } } - USF.GetMD().AddWordToAutoDictionary(M.W, M.Pos); + MD.AddWordToAutoDictionary(M.W, M.Pos); } } @@ -271,7 +271,7 @@ class TraceState { size_t Diff = NumMutations - FirstN; size_t DiffLog = sizeof(long) * 8 - __builtin_clzl((long)Diff); assert(DiffLog > 0 && DiffLog < 64); - bool WantThisOne = USF.GetRand()(1 << DiffLog) == 0; // 1 out of DiffLog. + bool WantThisOne = MD.GetRand()(1 << DiffLog) == 0; // 1 out of DiffLog. return WantThisOne; } @@ -279,7 +279,7 @@ class TraceState { size_t NumMutations; TraceBasedMutation Mutations[kMaxMutations]; LabelRange LabelRanges[1 << (sizeof(dfsan_label) * 8)]; - UserSuppliedFuzzer &USF; + MutationDispatcher &MD; const Fuzzer::FuzzingOptions &Options; uint8_t **CurrentUnitData; size_t *CurrentUnitSize; @@ -486,7 +486,7 @@ void Fuzzer::AssignTaintLabels(uint8_t *Data, size_t Size) { void Fuzzer::InitializeTraceState() { if (!Options.UseTraces && !Options.UseMemcmp) return; - TS = new TraceState(USF, Options, &CurrentUnitData, &CurrentUnitSize); + TS = new TraceState(MD, Options, &CurrentUnitData, &CurrentUnitSize); if (ReallyHaveDFSan()) { for (size_t i = 0; i < static_cast(Options.MaxLen); i++) { dfsan_label L = dfsan_create_label("input", (void *)(i + 1)); diff --git a/llvm/lib/Fuzzer/test/FuzzerUnittest.cpp b/llvm/lib/Fuzzer/test/FuzzerUnittest.cpp index 5213280..06ab510 100644 --- a/llvm/lib/Fuzzer/test/FuzzerUnittest.cpp +++ b/llvm/lib/Fuzzer/test/FuzzerUnittest.cpp @@ -403,9 +403,9 @@ TEST(FuzzerUtil, Base64) { TEST(Corpus, Distribution) { Random Rand(0); - SimpleUserSuppliedFuzzer USF(&Rand, LLVMFuzzerTestOneInput); + MutationDispatcher MD(Rand); Fuzzer::FuzzingOptions Options; - Fuzzer Fuzz(USF, Options); + Fuzzer Fuzz(LLVMFuzzerTestOneInput, MD, Options); size_t N = 10; size_t TriesPerUnit = 1<<20; for (size_t i = 0; i < N; i++) { diff --git a/llvm/lib/Fuzzer/test/fuzzer-dfsan.test b/llvm/lib/Fuzzer/test/fuzzer-dfsan.test index b7c887b..6700771 100644 --- a/llvm/lib/Fuzzer/test/fuzzer-dfsan.test +++ b/llvm/lib/Fuzzer/test/fuzzer-dfsan.test @@ -7,7 +7,7 @@ CHECK_DFSanCmpCallback: DFSanCmpCallback: PC CHECK_DFSanSwitchCallback: DFSanSwitchCallback: PC CHECK_DFSanMemcmpCallback: DFSanMemcmpCallback: Pos -RUN: not LLVMFuzzer-SimpleCmpTest-DFSan -use_traces=1 -seed=1 -runs=1000000 -timeout=5 2>&1 | FileCheck %s --check-prefix=CHECK1 +RUN: not LLVMFuzzer-SimpleCmpTest-DFSan -use_traces=1 -seed=1 -runs=10000000 -timeout=5 2>&1 | FileCheck %s --check-prefix=CHECK1 RUN: LLVMFuzzer-SimpleCmpTest-DFSan -use_traces=1 -seed=1 -runs=100 -timeout=5 -verbosity=3 2>&1 | FileCheck %s -check-prefix=CHECK_DFSanCmpCallback RUN: not LLVMFuzzer-MemcmpTest-DFSan -use_traces=1 -seed=1 -runs=100000 -timeout=5 2>&1 | FileCheck %s --check-prefix=CHECK2 diff --git a/llvm/lib/Fuzzer/test/fuzzer.test b/llvm/lib/Fuzzer/test/fuzzer.test index 4b1e524..3d9f5b4 100644 --- a/llvm/lib/Fuzzer/test/fuzzer.test +++ b/llvm/lib/Fuzzer/test/fuzzer.test @@ -59,6 +59,7 @@ RUN: not LLVMFuzzer-LeakTest -runs=10 2>&1 | FileCheck %s --check-prefix=LEAK LEAK: ERROR: LeakSanitizer: detected memory leaks LEAK-NOT: DEATH: +RUN: mkdir -p %t RUN: echo abcd > %t/NthRunCrashTest.in RUN: LLVMFuzzer-NthRunCrashTest %t/NthRunCrashTest.in RUN: LLVMFuzzer-NthRunCrashTest %t/NthRunCrashTest.in -runs=10 -- 2.7.4