13cab2bb3Spatrick //===- FuzzerInternal.h - Internal header for the Fuzzer --------*- C++ -* ===// 23cab2bb3Spatrick // 33cab2bb3Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 43cab2bb3Spatrick // See https://llvm.org/LICENSE.txt for license information. 53cab2bb3Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 63cab2bb3Spatrick // 73cab2bb3Spatrick //===----------------------------------------------------------------------===// 83cab2bb3Spatrick // Define the main class fuzzer::Fuzzer and most functions. 93cab2bb3Spatrick //===----------------------------------------------------------------------===// 103cab2bb3Spatrick 113cab2bb3Spatrick #ifndef LLVM_FUZZER_INTERNAL_H 123cab2bb3Spatrick #define LLVM_FUZZER_INTERNAL_H 133cab2bb3Spatrick 143cab2bb3Spatrick #include "FuzzerDataFlowTrace.h" 153cab2bb3Spatrick #include "FuzzerDefs.h" 163cab2bb3Spatrick #include "FuzzerExtFunctions.h" 173cab2bb3Spatrick #include "FuzzerInterface.h" 183cab2bb3Spatrick #include "FuzzerOptions.h" 193cab2bb3Spatrick #include "FuzzerSHA1.h" 203cab2bb3Spatrick #include "FuzzerValueBitMap.h" 213cab2bb3Spatrick #include <algorithm> 223cab2bb3Spatrick #include <atomic> 233cab2bb3Spatrick #include <chrono> 243cab2bb3Spatrick #include <climits> 253cab2bb3Spatrick #include <cstdlib> 263cab2bb3Spatrick #include <string.h> 273cab2bb3Spatrick 283cab2bb3Spatrick namespace fuzzer { 293cab2bb3Spatrick 303cab2bb3Spatrick using namespace std::chrono; 313cab2bb3Spatrick 323cab2bb3Spatrick class Fuzzer { 333cab2bb3Spatrick public: 343cab2bb3Spatrick 353cab2bb3Spatrick Fuzzer(UserCallback CB, InputCorpus &Corpus, MutationDispatcher &MD, 363cab2bb3Spatrick FuzzingOptions Options); 373cab2bb3Spatrick ~Fuzzer(); 38*810390e3Srobert void Loop(std::vector<SizedFile> &CorporaFiles); 39*810390e3Srobert void ReadAndExecuteSeedCorpora(std::vector<SizedFile> &CorporaFiles); 403cab2bb3Spatrick void MinimizeCrashLoop(const Unit &U); 413cab2bb3Spatrick void RereadOutputCorpus(size_t MaxSize); 423cab2bb3Spatrick secondsSinceProcessStartUp()433cab2bb3Spatrick size_t secondsSinceProcessStartUp() { 443cab2bb3Spatrick return duration_cast<seconds>(system_clock::now() - ProcessStartTime) 453cab2bb3Spatrick .count(); 463cab2bb3Spatrick } 473cab2bb3Spatrick TimedOut()483cab2bb3Spatrick bool TimedOut() { 493cab2bb3Spatrick return Options.MaxTotalTimeSec > 0 && 503cab2bb3Spatrick secondsSinceProcessStartUp() > 513cab2bb3Spatrick static_cast<size_t>(Options.MaxTotalTimeSec); 523cab2bb3Spatrick } 533cab2bb3Spatrick execPerSec()543cab2bb3Spatrick size_t execPerSec() { 553cab2bb3Spatrick size_t Seconds = secondsSinceProcessStartUp(); 563cab2bb3Spatrick return Seconds ? TotalNumberOfRuns / Seconds : 0; 573cab2bb3Spatrick } 583cab2bb3Spatrick getTotalNumberOfRuns()593cab2bb3Spatrick size_t getTotalNumberOfRuns() { return TotalNumberOfRuns; } 603cab2bb3Spatrick 613cab2bb3Spatrick static void StaticAlarmCallback(); 623cab2bb3Spatrick static void StaticCrashSignalCallback(); 633cab2bb3Spatrick static void StaticExitCallback(); 643cab2bb3Spatrick static void StaticInterruptCallback(); 653cab2bb3Spatrick static void StaticFileSizeExceedCallback(); 663cab2bb3Spatrick static void StaticGracefulExitCallback(); 673cab2bb3Spatrick 68*810390e3Srobert // Executes the target callback on {Data, Size} once. 69*810390e3Srobert // Returns false if the input was rejected by the target (target returned -1), 70*810390e3Srobert // and true otherwise. 71*810390e3Srobert bool ExecuteCallback(const uint8_t *Data, size_t Size); 723cab2bb3Spatrick bool RunOne(const uint8_t *Data, size_t Size, bool MayDeleteFile = false, 73d89ec533Spatrick InputInfo *II = nullptr, bool ForceAddToCorpus = false, 74d89ec533Spatrick bool *FoundUniqFeatures = nullptr); 75d89ec533Spatrick void TPCUpdateObservedPCs(); 763cab2bb3Spatrick 773cab2bb3Spatrick // Merge Corpora[1:] into Corpora[0]. 78*810390e3Srobert void Merge(const std::vector<std::string> &Corpora); 79*810390e3Srobert void CrashResistantMergeInternalStep(const std::string &ControlFilePath, 80*810390e3Srobert bool IsSetCoverMerge); GetMD()813cab2bb3Spatrick MutationDispatcher &GetMD() { return MD; } 823cab2bb3Spatrick void PrintFinalStats(); 833cab2bb3Spatrick void SetMaxInputLen(size_t MaxInputLen); 843cab2bb3Spatrick void SetMaxMutationLen(size_t MaxMutationLen); 853cab2bb3Spatrick void RssLimitCallback(); 863cab2bb3Spatrick InFuzzingThread()873cab2bb3Spatrick bool InFuzzingThread() const { return IsMyThread; } 883cab2bb3Spatrick size_t GetCurrentUnitInFuzzingThead(const uint8_t **Data) const; 893cab2bb3Spatrick void TryDetectingAMemoryLeak(const uint8_t *Data, size_t Size, 903cab2bb3Spatrick bool DuringInitialCorpusExecution); 913cab2bb3Spatrick 923cab2bb3Spatrick void HandleMalloc(size_t Size); 933cab2bb3Spatrick static void MaybeExitGracefully(); 94*810390e3Srobert static int InterruptExitCode(); 953cab2bb3Spatrick std::string WriteToOutputCorpus(const Unit &U); 963cab2bb3Spatrick 973cab2bb3Spatrick private: 983cab2bb3Spatrick void AlarmCallback(); 993cab2bb3Spatrick void CrashCallback(); 1003cab2bb3Spatrick void ExitCallback(); 1013cab2bb3Spatrick void CrashOnOverwrittenData(); 1023cab2bb3Spatrick void InterruptCallback(); 1033cab2bb3Spatrick void MutateAndTestOne(); 1043cab2bb3Spatrick void PurgeAllocator(); 1053cab2bb3Spatrick void ReportNewCoverage(InputInfo *II, const Unit &U); 1063cab2bb3Spatrick void PrintPulseAndReportSlowInput(const uint8_t *Data, size_t Size); 1073cab2bb3Spatrick void WriteUnitToFileWithPrefix(const Unit &U, const char *Prefix); 1083cab2bb3Spatrick void PrintStats(const char *Where, const char *End = "\n", size_t Units = 0, 1093cab2bb3Spatrick size_t Features = 0); 1103cab2bb3Spatrick void PrintStatusForNewUnit(const Unit &U, const char *Text); 1113cab2bb3Spatrick void CheckExitOnSrcPosOrItem(); 1123cab2bb3Spatrick 1133cab2bb3Spatrick static void StaticDeathCallback(); 1143cab2bb3Spatrick void DumpCurrentUnit(const char *Prefix); 1153cab2bb3Spatrick void DeathCallback(); 1163cab2bb3Spatrick 1173cab2bb3Spatrick void AllocateCurrentUnitData(); 1183cab2bb3Spatrick uint8_t *CurrentUnitData = nullptr; 1193cab2bb3Spatrick std::atomic<size_t> CurrentUnitSize; 1203cab2bb3Spatrick uint8_t BaseSha1[kSHA1NumBytes]; // Checksum of the base unit. 1213cab2bb3Spatrick 1223cab2bb3Spatrick bool GracefulExitRequested = false; 1233cab2bb3Spatrick 1243cab2bb3Spatrick size_t TotalNumberOfRuns = 0; 1253cab2bb3Spatrick size_t NumberOfNewUnitsAdded = 0; 1263cab2bb3Spatrick 1273cab2bb3Spatrick size_t LastCorpusUpdateRun = 0; 1283cab2bb3Spatrick 1293cab2bb3Spatrick bool HasMoreMallocsThanFrees = false; 1303cab2bb3Spatrick size_t NumberOfLeakDetectionAttempts = 0; 1313cab2bb3Spatrick 1323cab2bb3Spatrick system_clock::time_point LastAllocatorPurgeAttemptTime = system_clock::now(); 1333cab2bb3Spatrick 1343cab2bb3Spatrick UserCallback CB; 1353cab2bb3Spatrick InputCorpus &Corpus; 1363cab2bb3Spatrick MutationDispatcher &MD; 1373cab2bb3Spatrick FuzzingOptions Options; 1383cab2bb3Spatrick DataFlowTrace DFT; 1393cab2bb3Spatrick 1403cab2bb3Spatrick system_clock::time_point ProcessStartTime = system_clock::now(); 1413cab2bb3Spatrick system_clock::time_point UnitStartTime, UnitStopTime; 1423cab2bb3Spatrick long TimeOfLongestUnitInSeconds = 0; 1433cab2bb3Spatrick long EpochOfLastReadOfOutputCorpus = 0; 1443cab2bb3Spatrick 1453cab2bb3Spatrick size_t MaxInputLen = 0; 1463cab2bb3Spatrick size_t MaxMutationLen = 0; 1473cab2bb3Spatrick size_t TmpMaxMutationLen = 0; 1483cab2bb3Spatrick 149*810390e3Srobert std::vector<uint32_t> UniqFeatureSetTmp; 1503cab2bb3Spatrick 1513cab2bb3Spatrick // Need to know our own thread. 1523cab2bb3Spatrick static thread_local bool IsMyThread; 1533cab2bb3Spatrick }; 1543cab2bb3Spatrick 1553cab2bb3Spatrick struct ScopedEnableMsanInterceptorChecks { ScopedEnableMsanInterceptorChecksScopedEnableMsanInterceptorChecks1563cab2bb3Spatrick ScopedEnableMsanInterceptorChecks() { 1573cab2bb3Spatrick if (EF->__msan_scoped_enable_interceptor_checks) 1583cab2bb3Spatrick EF->__msan_scoped_enable_interceptor_checks(); 1593cab2bb3Spatrick } ~ScopedEnableMsanInterceptorChecksScopedEnableMsanInterceptorChecks1603cab2bb3Spatrick ~ScopedEnableMsanInterceptorChecks() { 1613cab2bb3Spatrick if (EF->__msan_scoped_disable_interceptor_checks) 1623cab2bb3Spatrick EF->__msan_scoped_disable_interceptor_checks(); 1633cab2bb3Spatrick } 1643cab2bb3Spatrick }; 1653cab2bb3Spatrick 1663cab2bb3Spatrick struct ScopedDisableMsanInterceptorChecks { ScopedDisableMsanInterceptorChecksScopedDisableMsanInterceptorChecks1673cab2bb3Spatrick ScopedDisableMsanInterceptorChecks() { 1683cab2bb3Spatrick if (EF->__msan_scoped_disable_interceptor_checks) 1693cab2bb3Spatrick EF->__msan_scoped_disable_interceptor_checks(); 1703cab2bb3Spatrick } ~ScopedDisableMsanInterceptorChecksScopedDisableMsanInterceptorChecks1713cab2bb3Spatrick ~ScopedDisableMsanInterceptorChecks() { 1723cab2bb3Spatrick if (EF->__msan_scoped_enable_interceptor_checks) 1733cab2bb3Spatrick EF->__msan_scoped_enable_interceptor_checks(); 1743cab2bb3Spatrick } 1753cab2bb3Spatrick }; 1763cab2bb3Spatrick 1773cab2bb3Spatrick } // namespace fuzzer 1783cab2bb3Spatrick 1793cab2bb3Spatrick #endif // LLVM_FUZZER_INTERNAL_H 180