X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FFuzzer%2FFuzzerInternal.h;h=c1e9daac98089c902cc5c84ffbe7894c6f86b536;hb=HEAD;hp=8d6193e9a229a0e1dd8d308846a6bb14d01eb7b0;hpb=05ef67b6b9f1efe216cb4c1bbe0e75b178b5fba2;p=oota-llvm.git diff --git a/lib/Fuzzer/FuzzerInternal.h b/lib/Fuzzer/FuzzerInternal.h index 8d6193e9a22..c1e9daac980 100644 --- a/lib/Fuzzer/FuzzerInternal.h +++ b/lib/Fuzzer/FuzzerInternal.h @@ -8,6 +8,10 @@ //===----------------------------------------------------------------------===// // Define the main class fuzzer::Fuzzer and most functions. //===----------------------------------------------------------------------===// + +#ifndef LLVM_FUZZER_INTERNAL_H +#define LLVM_FUZZER_INTERNAL_H + #include #include #include @@ -16,12 +20,10 @@ #include #include #include -#include #include "FuzzerInterface.h" namespace fuzzer { -typedef std::vector Unit; using namespace std::chrono; std::string FileToString(const std::string &Path); @@ -34,51 +36,79 @@ void CopyFileToErr(const std::string &Path); std::string DirPlusFile(const std::string &DirPath, const std::string &FileName); -void Mutate(Unit *U, size_t MaxLen); - -void CrossOver(const Unit &A, const Unit &B, Unit *U, size_t MaxLen); - +void Printf(const char *Fmt, ...); void Print(const Unit &U, const char *PrintAfter = ""); +void PrintASCII(const uint8_t *Data, size_t Size, 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); +std::string Base64(const Unit &U); +int 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); +// Changes U to contain only ASCII (isprint+isspace) characters. +// Returns true iff U has been changed. +bool ToASCII(Unit &U); +bool IsASCII(const Unit &U); + int NumberOfCpuCores(); +int GetPid(); + +// Dictionary. + +// Parses one dictionary entry. +// If successfull, write the enty to Unit and returns true, +// otherwise returns false. +bool ParseOneDictionaryEntry(const std::string &Str, Unit *U); +// Parses the dictionary file, fills Units, returns true iff all lines +// were parsed succesfully. +bool ParseDictionaryFile(const std::string &Text, std::vector *Units); class Fuzzer { public: struct FuzzingOptions { int Verbosity = 1; int MaxLen = 0; + int UnitTimeoutSec = 300; + int MaxTotalTimeSec = 0; bool DoCrossOver = true; int MutateDepth = 5; bool ExitOnFirst = false; bool UseCounters = false; + bool UseIndirCalls = true; bool UseTraces = false; bool UseFullCoverageSet = false; - bool UseCoveragePairs = false; bool Reload = true; + bool ShuffleAtStartUp = true; int PreferSmallDuringInitialShuffle = -1; size_t MaxNumberOfRuns = ULONG_MAX; int SyncTimeout = 600; + int ReportSlowUnits = 10; + bool OnlyASCII = false; std::string OutputCorpus; std::string SyncCommand; - std::vector Tokens; + std::string ArtifactPrefix = "./"; + std::string ExactArtifactPath; + bool SaveArtifacts = true; + bool PrintNEW = true; // Print a status line when new units are found; + bool OutputCSV = false; + bool PrintNewCovPcs = false; }; - Fuzzer(UserCallback Callback, FuzzingOptions Options); + Fuzzer(UserSuppliedFuzzer &USF, FuzzingOptions Options); void AddToCorpus(const Unit &U) { Corpus.push_back(U); } - void Loop(size_t NumIterations); + size_t ChooseUnitIdxToMutate(); + const Unit &ChooseUnitToMutate() { return Corpus[ChooseUnitIdxToMutate()]; }; + void Loop(); + void Drill(); void ShuffleAndMinimize(); void InitializeTraceState(); size_t CorpusSize() const { return Corpus.size(); } void ReadDir(const std::string &Path, long *Epoch) { + Printf("Loading corpus: %s\n", Path.c_str()); ReadDirToVectorOfUnits(Path.c_str(), &Corpus, Epoch); } void RereadOutputCorpus(); @@ -94,35 +124,39 @@ class Fuzzer { static void StaticAlarmCallback(); - Unit SubstituteTokens(const Unit &U) const; + void ExecuteCallback(const Unit &U); + + // Merge Corpora[1:] into Corpora[0]. + void Merge(const std::vector &Corpora); private: 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 MutateAndTestOne(); + void ReportNewCoverage(const Unit &U); + bool RunOne(const Unit &U); + void RunOneAndUpdateCorpus(Unit &U); void WriteToOutputCorpus(const Unit &U); - void WriteToCrash(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 WriteUnitToFileWithPrefix(const Unit &U, const char *Prefix); + void PrintStats(const char *Where, const char *End = "\n"); + void PrintStatusForNewUnit(const Unit &U); + void PrintUnitInASCII(const Unit &U, const char *PrintAfter = ""); void SyncCorpus(); + size_t RecordBlockCoverage(); + size_t RecordCallerCalleeCoverage(); + void PrepareCoverageBeforeRun(); + bool CheckCoverageAfterRun(); + + // 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); + // Stop tracing. + void StopTraceRecording(); void SetDeathCallback(); static void StaticDeathCallback(); @@ -130,11 +164,10 @@ class Fuzzer { Unit CurrentUnit; size_t TotalNumberOfRuns = 0; + size_t TotalNumberOfExecutedTraceBasedMutations = 0; std::vector Corpus; - std::set UnitsAddedAfterInitialLoad; - std::unordered_set FullCoverageSets; - std::unordered_set CoveragePairs; + std::unordered_set UnitHashesAddedToCorpus; // For UseCounters std::vector CounterBitmap; @@ -144,13 +177,31 @@ class Fuzzer { return Res; } - UserCallback Callback; + UserSuppliedFuzzer &USF; FuzzingOptions Options; system_clock::time_point ProcessStartTime = system_clock::now(); system_clock::time_point LastExternalSync = system_clock::now(); system_clock::time_point UnitStartTime; long TimeOfLongestUnitInSeconds = 0; long EpochOfLastReadOfOutputCorpus = 0; + size_t LastRecordedBlockCoverage = 0; + size_t LastRecordedCallerCalleeCoverage = 0; + size_t LastCoveragePcBufferLen = 0; +}; + +class SimpleUserSuppliedFuzzer: public UserSuppliedFuzzer { + public: + SimpleUserSuppliedFuzzer(FuzzerRandomBase *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