1 //===- FuzzerInternal.h - Internal header for the Fuzzer --------*- C++ -* ===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // Define the main class fuzzer::Fuzzer and most functions. 10 //===----------------------------------------------------------------------===// 11 #include <cassert> 12 #include <climits> 13 #include <chrono> 14 #include <cstddef> 15 #include <cstdlib> 16 #include <string> 17 #include <vector> 18 #include <unordered_set> 19 20 #include "FuzzerInterface.h" 21 22 namespace fuzzer { 23 typedef std::vector<uint8_t> Unit; 24 using namespace std::chrono; 25 26 std::string FileToString(const std::string &Path); 27 Unit FileToVector(const std::string &Path); 28 void ReadDirToVectorOfUnits(const char *Path, std::vector<Unit> *V); 29 void WriteToFile(const Unit &U, const std::string &Path); 30 void CopyFileToErr(const std::string &Path); 31 // Returns "Dir/FileName" or equivalent for the current OS. 32 std::string DirPlusFile(const std::string &DirPath, 33 const std::string &FileName); 34 35 void Mutate(Unit *U, size_t MaxLen); 36 37 void CrossOver(const Unit &A, const Unit &B, Unit *U, size_t MaxLen); 38 39 void Print(const Unit &U, const char *PrintAfter = ""); 40 void PrintASCII(const Unit &U, const char *PrintAfter = ""); 41 std::string Hash(const Unit &U); 42 void SetTimer(int Seconds); 43 44 class Fuzzer { 45 public: 46 struct FuzzingOptions { 47 int Verbosity = 1; 48 int MaxLen = 0; 49 bool DoCrossOver = true; 50 int MutateDepth = 5; 51 bool ExitOnFirst = false; 52 bool UseCounters = false; 53 bool UseFullCoverageSet = false; 54 bool UseCoveragePairs = false; 55 bool UseDFSan = false; 56 int PreferSmallDuringInitialShuffle = -1; 57 size_t MaxNumberOfRuns = ULONG_MAX; 58 std::string OutputCorpus; 59 std::vector<std::string> Tokens; 60 }; 61 Fuzzer(UserCallback Callback, FuzzingOptions Options); AddToCorpus(const Unit & U)62 void AddToCorpus(const Unit &U) { Corpus.push_back(U); } 63 size_t Loop(size_t NumIterations); 64 void ShuffleAndMinimize(); 65 void InitializeDFSan(); CorpusSize()66 size_t CorpusSize() const { return Corpus.size(); } ReadDir(const std::string & Path)67 void ReadDir(const std::string &Path) { 68 ReadDirToVectorOfUnits(Path.c_str(), &Corpus); 69 } 70 // Save the current corpus to OutputCorpus. 71 void SaveCorpus(); 72 secondsSinceProcessStartUp()73 size_t secondsSinceProcessStartUp() { 74 return duration_cast<seconds>(system_clock::now() - ProcessStartTime) 75 .count(); 76 } 77 getTotalNumberOfRuns()78 size_t getTotalNumberOfRuns() { return TotalNumberOfRuns; } 79 80 static void StaticAlarmCallback(); 81 82 Unit SubstituteTokens(const Unit &U) const; 83 84 private: 85 void AlarmCallback(); 86 void ExecuteCallback(const Unit &U); 87 size_t MutateAndTestOne(Unit *U); 88 size_t RunOne(const Unit &U); 89 size_t RunOneMaximizeTotalCoverage(const Unit &U); 90 size_t RunOneMaximizeFullCoverageSet(const Unit &U); 91 size_t RunOneMaximizeCoveragePairs(const Unit &U); 92 void WriteToOutputCorpus(const Unit &U); 93 void WriteToCrash(const Unit &U, const char *Prefix); 94 bool MutateWithDFSan(Unit *U); 95 void PrintStats(const char *Where, size_t Cov, const char *End = "\n"); 96 void PrintUnitInASCIIOrTokens(const Unit &U, const char *PrintAfter = ""); 97 98 void SetDeathCallback(); 99 static void StaticDeathCallback(); 100 void DeathCallback(); 101 Unit CurrentUnit; 102 103 size_t TotalNumberOfRuns = 0; 104 105 std::vector<Unit> Corpus; 106 std::unordered_set<uintptr_t> FullCoverageSets; 107 std::unordered_set<uint64_t> CoveragePairs; 108 109 // For UseCounters 110 std::vector<uint8_t> CounterBitmap; TotalBits()111 size_t TotalBits() { // Slow. Call it only for printing stats. 112 size_t Res = 0; 113 for (auto x : CounterBitmap) Res += __builtin_popcount(x); 114 return Res; 115 } 116 117 UserCallback Callback; 118 FuzzingOptions Options; 119 system_clock::time_point ProcessStartTime = system_clock::now(); 120 system_clock::time_point UnitStartTime; 121 long TimeOfLongestUnitInSeconds = 0; 122 }; 123 124 }; // namespace fuzzer 125