From 1bb500faf8c85e76dcb0b4f0087cb051ee0c98db Mon Sep 17 00:00:00 2001 From: Kostya Serebryany Date: Sat, 13 Feb 2016 02:39:30 +0000 Subject: [PATCH] [libFuzzer] remove UserSuppliedFuzzer from the interface (it was a bad idea). llvm-svn: 260796 --- lib/Fuzzer/FuzzerDriver.cpp | 16 +--- lib/Fuzzer/FuzzerInterface.h | 98 ++-------------------- lib/Fuzzer/FuzzerInternal.h | 60 +++++++++++++ lib/Fuzzer/test/CMakeLists.txt | 1 - lib/Fuzzer/test/UserSuppliedFuzzerTest.cpp | 51 ----------- lib/Fuzzer/test/fuzzer.test | 2 - 6 files changed, 68 insertions(+), 160 deletions(-) delete mode 100644 lib/Fuzzer/test/UserSuppliedFuzzerTest.cpp diff --git a/lib/Fuzzer/FuzzerDriver.cpp b/lib/Fuzzer/FuzzerDriver.cpp index 6cdbe4f34d6..841870061ed 100644 --- a/lib/Fuzzer/FuzzerDriver.cpp +++ b/lib/Fuzzer/FuzzerDriver.cpp @@ -243,24 +243,14 @@ static bool AllInputsAreFiles() { int FuzzerDriver(int argc, char **argv, UserCallback Callback) { FuzzerRandom_mt19937 Rand(0); - SimpleUserSuppliedFuzzer SUSF(&Rand, Callback); - return FuzzerDriver(argc, argv, SUSF); -} - -int FuzzerDriver(int argc, char **argv, UserSuppliedFuzzer &USF) { std::vector Args(argv, argv + argc); - return FuzzerDriver(Args, USF); + return FuzzerDriver(Args, Callback); } int FuzzerDriver(const std::vector &Args, UserCallback Callback) { - FuzzerRandom_mt19937 Rand(0); - SimpleUserSuppliedFuzzer SUSF(&Rand, Callback); - return FuzzerDriver(Args, SUSF); -} - -int FuzzerDriver(const std::vector &Args, - UserSuppliedFuzzer &USF) { using namespace fuzzer; + FuzzerRandom_mt19937 Rand(0); + SimpleUserSuppliedFuzzer USF(&Rand, Callback); assert(!Args.empty()); ProgName = new std::string(Args[0]); ParseFlags(Args); diff --git a/lib/Fuzzer/FuzzerInterface.h b/lib/Fuzzer/FuzzerInterface.h index 663cd5e7fdb..04e9b8350b9 100644 --- a/lib/Fuzzer/FuzzerInterface.h +++ b/lib/Fuzzer/FuzzerInterface.h @@ -64,6 +64,7 @@ int LLVMFuzzerInitialize(int *argc, char ***argv) { } // Implement your own main() or use the one from FuzzerMain.cpp. +// *NOT* recommended for most cases. int main(int argc, char **argv) { InitializeMeIfNeeded(); return fuzzer::FuzzerDriver(argc, argv, LLVMFuzzerTestOneInput); @@ -72,102 +73,13 @@ int main(int argc, char **argv) { */ int FuzzerDriver(int argc, char **argv, UserCallback Callback); -class FuzzerRandomBase { - public: - FuzzerRandomBase(){} - virtual ~FuzzerRandomBase(){}; - virtual void ResetSeed(unsigned int seed) = 0; - // Return a random number. - virtual size_t Rand() = 0; - // Return a random number in range [0,n). - size_t operator()(size_t n) { return n ? Rand() % n : 0; } - bool RandBool() { return Rand() % 2; } -}; - -// Using libc's stand/rand. -class FuzzerRandomLibc : public FuzzerRandomBase { - public: - FuzzerRandomLibc(unsigned int seed) { ResetSeed(seed); } - void ResetSeed(unsigned int seed) override; - ~FuzzerRandomLibc() override {}; - size_t Rand() override; -}; - -// Using std::mt19937 -class FuzzerRandom_mt19937 : public FuzzerRandomBase { - public: - FuzzerRandom_mt19937(unsigned int seed) { ResetSeed(seed); } - void ResetSeed(unsigned int seed) override; - ~FuzzerRandom_mt19937() override; - size_t Rand() override; - private: - struct Impl; - Impl *R = nullptr; -}; - -// For backward compatibility only, deprecated. -size_t Mutate(uint8_t *Data, size_t Size, size_t MaxSize, - FuzzerRandomBase &Rand); - -size_t Mutate(uint8_t *Data, size_t Size, size_t MaxSize, unsigned int Seed); - -class MutationDispatcher; - -/** An abstract class that allows to use user-supplied mutators with libFuzzer. - -Usage: - -#\code -#include "FuzzerInterface.h" -class MyFuzzer : public fuzzer::UserSuppliedFuzzer { - public: - MyFuzzer(fuzzer::FuzzerRandomBase *Rand); - // Must define the target function. - int TargetFunction(...) { ...; return 0; } - // Optionally define the mutator. - size_t Mutate(...) { ... } - // Optionally define the CrossOver method. - size_t CrossOver(...) { ... } -}; - -int main(int argc, char **argv) { - MyFuzzer F; - fuzzer::FuzzerDriver(argc, argv, F); -} -#\endcode -*/ -class UserSuppliedFuzzer { - public: - UserSuppliedFuzzer(FuzzerRandomBase *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(); - - FuzzerRandomBase &GetRand() { return *Rand; } - - MutationDispatcher &GetMD() { return *MD; } - - private: - bool OwnRand = false; - FuzzerRandomBase *Rand; - MutationDispatcher *MD; -}; - -/// Runs the fuzzing with the UserSuppliedFuzzer. -int FuzzerDriver(int argc, char **argv, UserSuppliedFuzzer &USF); - /// More C++-ish interface. -int FuzzerDriver(const std::vector &Args, UserSuppliedFuzzer &USF); int FuzzerDriver(const std::vector &Args, UserCallback Callback); +// Same interface as LLVMFuzzerTestOneInput. +// Can be used inside the user-supplied LLVMFuzzerTestOneInput. +size_t Mutate(uint8_t *Data, size_t Size, size_t MaxSize, unsigned int Seed); + } // namespace fuzzer #endif // LLVM_FUZZER_INTERFACE_H diff --git a/lib/Fuzzer/FuzzerInternal.h b/lib/Fuzzer/FuzzerInternal.h index 07f45af08ff..f57e24f739f 100644 --- a/lib/Fuzzer/FuzzerInternal.h +++ b/lib/Fuzzer/FuzzerInternal.h @@ -98,6 +98,41 @@ bool IsASCII(const Unit &U); int NumberOfCpuCores(); int GetPid(); +class FuzzerRandomBase { + public: + FuzzerRandomBase(){} + virtual ~FuzzerRandomBase(){}; + virtual void ResetSeed(unsigned int seed) = 0; + // Return a random number. + virtual size_t Rand() = 0; + // Return a random number in range [0,n). + size_t operator()(size_t n) { return n ? Rand() % n : 0; } + bool RandBool() { return Rand() % 2; } +}; + +// Using libc's stand/rand. +class FuzzerRandomLibc : public FuzzerRandomBase { + public: + FuzzerRandomLibc(unsigned int seed) { ResetSeed(seed); } + void ResetSeed(unsigned int seed) override; + ~FuzzerRandomLibc() override {}; + size_t Rand() override; +}; + +// Using std::mt19937 +class FuzzerRandom_mt19937 : public FuzzerRandomBase { + public: + FuzzerRandom_mt19937(unsigned int seed) { ResetSeed(seed); } + void ResetSeed(unsigned int seed) override; + ~FuzzerRandom_mt19937() override; + size_t Rand() override; + private: + struct Impl; + Impl *R = nullptr; +}; + + + // Dictionary. // Parses one dictionary entry. @@ -169,6 +204,31 @@ private: Impl *MDImpl; }; +class UserSuppliedFuzzer { + public: + UserSuppliedFuzzer(FuzzerRandomBase *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(); + + FuzzerRandomBase &GetRand() { return *Rand; } + + MutationDispatcher &GetMD() { return *MD; } + + private: + bool OwnRand = false; + FuzzerRandomBase *Rand; + MutationDispatcher *MD; +}; + class Fuzzer { public: struct FuzzingOptions { diff --git a/lib/Fuzzer/test/CMakeLists.txt b/lib/Fuzzer/test/CMakeLists.txt index f7ed87e251f..709e96bf615 100644 --- a/lib/Fuzzer/test/CMakeLists.txt +++ b/lib/Fuzzer/test/CMakeLists.txt @@ -37,7 +37,6 @@ set(Tests ) set(CustomMainTests - UserSuppliedFuzzerTest ) set(UninstrumentedTests diff --git a/lib/Fuzzer/test/UserSuppliedFuzzerTest.cpp b/lib/Fuzzer/test/UserSuppliedFuzzerTest.cpp deleted file mode 100644 index 59f83b57bfa..00000000000 --- a/lib/Fuzzer/test/UserSuppliedFuzzerTest.cpp +++ /dev/null @@ -1,51 +0,0 @@ -// Simple test for a fuzzer. -// The fuzzer must find the string "Hi!" preceded by a magic value. -// Uses UserSuppliedFuzzer which ensures that the magic is present. -#include -#include -#include -#include -#include -#include - -#include "FuzzerInterface.h" - -static const uint64_t kMagic = 8860221463604ULL; - -class MyFuzzer : public fuzzer::UserSuppliedFuzzer { - public: - MyFuzzer(fuzzer::FuzzerRandomBase *Rand) - : fuzzer::UserSuppliedFuzzer(Rand) {} - int TargetFunction(const uint8_t *Data, size_t Size) { - if (Size <= 10) return 0; - if (memcmp(Data, &kMagic, sizeof(kMagic))) return 0; - // It's hard to get here w/o advanced fuzzing techniques (e.g. cmp tracing). - // So, we simply 'fix' the data in the custom mutator. - if (Data[8] == 'H') { - if (Data[9] == 'i') { - if (Data[10] == '!') { - std::cout << "BINGO; Found the target, exiting\n"; - exit(1); - } - } - } - return 0; - } - // Custom mutator. - virtual size_t Mutate(uint8_t *Data, size_t Size, size_t MaxSize) { - assert(MaxSize > sizeof(kMagic)); - if (Size < sizeof(kMagic)) - Size = sizeof(kMagic); - // "Fix" the data, then mutate. - memcpy(Data, &kMagic, std::min(MaxSize, sizeof(kMagic))); - return fuzzer::UserSuppliedFuzzer::Mutate( - Data + sizeof(kMagic), Size - sizeof(kMagic), MaxSize - sizeof(kMagic)); - } - // No need to redefine CrossOver() here. -}; - -int main(int argc, char **argv) { - fuzzer::FuzzerRandomLibc Rand(0); - MyFuzzer F(&Rand); - fuzzer::FuzzerDriver(argc, argv, F); -} diff --git a/lib/Fuzzer/test/fuzzer.test b/lib/Fuzzer/test/fuzzer.test index 4638b97ed6b..4b1e524e251 100644 --- a/lib/Fuzzer/test/fuzzer.test +++ b/lib/Fuzzer/test/fuzzer.test @@ -24,8 +24,6 @@ RUN: not LLVMFuzzer-CallerCalleeTest -cross_over=0 -max_len= # LLVMFuzzer-CallerCalleeTest -use_indir_calls=0 -cross_over=0 -max_len=6 -seed=1 -runs=1000000 2>&1 | FileCheck %s --check-prefix=Done1000000 -RUN: not LLVMFuzzer-UserSuppliedFuzzerTest -seed=1 -timeout=15 2>&1 | FileCheck %s - RUN: not LLVMFuzzer-UninstrumentedTest-Uninstrumented 2>&1 | FileCheck %s --check-prefix=UNINSTRUMENTED UNINSTRUMENTED: ERROR: __sanitizer_set_death_callback is not defined. Exiting.