X-Git-Url: http://plrg.eecs.uci.edu/git/?p=oota-llvm.git;a=blobdiff_plain;f=lib%2FFuzzer%2FFuzzerInternal.h;h=274fdf077a7fb7582a066873a23db3bfc274857e;hp=e4e5eb7fd0516d0d35ac9dc2e61de5024af5bf2d;hb=8d4c8061c9a8d4ca6bf30cd21368073b7d64e136;hpb=ae0620c4e9be8e4be0ff3d7afad260f569742659 diff --git a/lib/Fuzzer/FuzzerInternal.h b/lib/Fuzzer/FuzzerInternal.h index e4e5eb7fd05..274fdf077a7 100644 --- a/lib/Fuzzer/FuzzerInternal.h +++ b/lib/Fuzzer/FuzzerInternal.h @@ -23,49 +23,70 @@ namespace fuzzer { typedef std::vector Unit; using namespace std::chrono; -Unit ReadFile(const char *Path); -void ReadDirToVectorOfUnits(const char *Path, std::vector *V); +std::string FileToString(const std::string &Path); +Unit FileToVector(const std::string &Path); +void ReadDirToVectorOfUnits(const char *Path, std::vector *V, + long *Epoch); void WriteToFile(const Unit &U, const std::string &Path); void CopyFileToErr(const std::string &Path); // Returns "Dir/FileName" or equivalent for the current OS. std::string DirPlusFile(const std::string &DirPath, const std::string &FileName); -void Mutate(Unit *U, size_t MaxLen); +size_t Mutate_EraseByte(uint8_t *Data, size_t size, size_t MaxSize, + FuzzerRandomBase &Rand); +size_t Mutate(uint8_t *Data, size_t Size, size_t MaxSize, + FuzzerRandomBase &Rand); -void CrossOver(const Unit &A, const Unit &B, Unit *U, size_t MaxLen); +size_t CrossOver(const uint8_t *Data1, size_t Size1, const uint8_t *Data2, + size_t Size2, uint8_t *Out, size_t MaxOutSize, + FuzzerRandomBase &Rand); +void Printf(const char *Fmt, ...); void Print(const Unit &U, const char *PrintAfter = ""); void PrintASCII(const Unit &U, const char *PrintAfter = ""); std::string Hash(const Unit &U); void SetTimer(int Seconds); +void PrintFileAsBase64(const std::string &Path); +void ExecuteCommand(const std::string &Command); + +// Private copy of SHA1 implementation. +static const int kSHA1NumBytes = 20; +// Computes SHA1 hash of 'Len' bytes in 'Data', writes kSHA1NumBytes to 'Out'. +void ComputeSHA1(const uint8_t *Data, size_t Len, uint8_t *Out); + +int NumberOfCpuCores(); class Fuzzer { public: struct FuzzingOptions { int Verbosity = 1; int MaxLen = 0; + int UnitTimeoutSec = 300; bool DoCrossOver = true; int MutateDepth = 5; bool ExitOnFirst = false; bool UseCounters = false; + bool UseTraces = false; bool UseFullCoverageSet = false; - bool UseCoveragePairs = false; + bool Reload = true; int PreferSmallDuringInitialShuffle = -1; size_t MaxNumberOfRuns = ULONG_MAX; + int SyncTimeout = 600; std::string OutputCorpus; + std::string SyncCommand; + std::vector Tokens; }; - Fuzzer(UserCallback Callback, FuzzingOptions Options) - : Callback(Callback), Options(Options) { - SetDeathCallback(); - } + Fuzzer(UserSuppliedFuzzer &USF, FuzzingOptions Options); void AddToCorpus(const Unit &U) { Corpus.push_back(U); } - size_t Loop(size_t NumIterations); + void Loop(size_t NumIterations); void ShuffleAndMinimize(); + void InitializeTraceState(); size_t CorpusSize() const { return Corpus.size(); } - void ReadDir(const std::string &Path) { - ReadDirToVectorOfUnits(Path.c_str(), &Corpus); + void ReadDir(const std::string &Path, long *Epoch) { + ReadDirToVectorOfUnits(Path.c_str(), &Corpus, Epoch); } + void RereadOutputCorpus(); // Save the current corpus to OutputCorpus. void SaveCorpus(); @@ -76,26 +97,48 @@ class Fuzzer { size_t getTotalNumberOfRuns() { return TotalNumberOfRuns; } - static void AlarmCallback(); + static void StaticAlarmCallback(); + + Unit SubstituteTokens(const Unit &U) const; private: - size_t MutateAndTestOne(Unit *U); + void AlarmCallback(); + void ExecuteCallback(const Unit &U); + void MutateAndTestOne(Unit *U); + void ReportNewCoverage(size_t NewCoverage, const Unit &U); size_t RunOne(const Unit &U); + void RunOneAndUpdateCorpus(const Unit &U); size_t RunOneMaximizeTotalCoverage(const Unit &U); size_t RunOneMaximizeFullCoverageSet(const Unit &U); size_t RunOneMaximizeCoveragePairs(const Unit &U); void WriteToOutputCorpus(const Unit &U); - static void WriteToCrash(const Unit &U, const char *Prefix); + void WriteUnitToFileWithPrefix(const Unit &U, const char *Prefix); + void PrintStats(const char *Where, size_t Cov, const char *End = "\n"); + void PrintUnitInASCIIOrTokens(const Unit &U, const char *PrintAfter = ""); + + void SyncCorpus(); + + // 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 and return the number of proposed mutations. + size_t StopTraceRecording(); + // Apply Idx-th trace-based mutation to U. + void ApplyTraceBasedMutation(size_t Idx, Unit *U); void SetDeathCallback(); - static void DeathCallback(); - static Unit CurrentUnit; + static void StaticDeathCallback(); + void DeathCallback(); + Unit CurrentUnit; size_t TotalNumberOfRuns = 0; std::vector Corpus; + std::unordered_set UnitHashesAddedToCorpus; std::unordered_set FullCoverageSets; - std::unordered_set CoveragePairs; // For UseCounters std::vector CounterBitmap; @@ -105,10 +148,25 @@ class Fuzzer { return Res; } - UserCallback Callback; + UserSuppliedFuzzer &USF; FuzzingOptions Options; system_clock::time_point ProcessStartTime = system_clock::now(); - static system_clock::time_point UnitStartTime; + system_clock::time_point LastExternalSync = system_clock::now(); + system_clock::time_point UnitStartTime; + long TimeOfLongestUnitInSeconds = 0; + long EpochOfLastReadOfOutputCorpus = 0; +}; + +class SimpleUserSuppliedFuzzer: public UserSuppliedFuzzer { + public: + SimpleUserSuppliedFuzzer(FuzzerRandomBase *Rand, UserCallback Callback) + : UserSuppliedFuzzer(Rand), Callback(Callback) {} + virtual void TargetFunction(const uint8_t *Data, size_t Size) { + return Callback(Data, Size); + } + + private: + UserCallback Callback; }; }; // namespace fuzzer