10b57cec5SDimitry Andric //===- FuzzerInternal.h - Internal header for the Fuzzer --------*- C++ -* ===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // Define the main class fuzzer::Fuzzer and most functions. 90b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 100b57cec5SDimitry Andric 110b57cec5SDimitry Andric #ifndef LLVM_FUZZER_INTERNAL_H 120b57cec5SDimitry Andric #define LLVM_FUZZER_INTERNAL_H 130b57cec5SDimitry Andric 140b57cec5SDimitry Andric #include "FuzzerDataFlowTrace.h" 150b57cec5SDimitry Andric #include "FuzzerDefs.h" 160b57cec5SDimitry Andric #include "FuzzerExtFunctions.h" 170b57cec5SDimitry Andric #include "FuzzerInterface.h" 180b57cec5SDimitry Andric #include "FuzzerOptions.h" 190b57cec5SDimitry Andric #include "FuzzerSHA1.h" 200b57cec5SDimitry Andric #include "FuzzerValueBitMap.h" 210b57cec5SDimitry Andric #include <algorithm> 220b57cec5SDimitry Andric #include <atomic> 230b57cec5SDimitry Andric #include <chrono> 240b57cec5SDimitry Andric #include <climits> 250b57cec5SDimitry Andric #include <cstdlib> 260b57cec5SDimitry Andric #include <string.h> 270b57cec5SDimitry Andric 280b57cec5SDimitry Andric namespace fuzzer { 290b57cec5SDimitry Andric 300b57cec5SDimitry Andric using namespace std::chrono; 310b57cec5SDimitry Andric 32*06c3fb27SDimitry Andric class Fuzzer final { 330b57cec5SDimitry Andric public: 340b57cec5SDimitry Andric Fuzzer(UserCallback CB, InputCorpus &Corpus, MutationDispatcher &MD, 35*06c3fb27SDimitry Andric const FuzzingOptions &Options); 36*06c3fb27SDimitry Andric ~Fuzzer() = delete; 37349cc55cSDimitry Andric void Loop(std::vector<SizedFile> &CorporaFiles); 38349cc55cSDimitry Andric void ReadAndExecuteSeedCorpora(std::vector<SizedFile> &CorporaFiles); 390b57cec5SDimitry Andric void MinimizeCrashLoop(const Unit &U); 400b57cec5SDimitry Andric void RereadOutputCorpus(size_t MaxSize); 410b57cec5SDimitry Andric secondsSinceProcessStartUp()420b57cec5SDimitry Andric size_t secondsSinceProcessStartUp() { 430b57cec5SDimitry Andric return duration_cast<seconds>(system_clock::now() - ProcessStartTime) 440b57cec5SDimitry Andric .count(); 450b57cec5SDimitry Andric } 460b57cec5SDimitry Andric TimedOut()470b57cec5SDimitry Andric bool TimedOut() { 480b57cec5SDimitry Andric return Options.MaxTotalTimeSec > 0 && 490b57cec5SDimitry Andric secondsSinceProcessStartUp() > 500b57cec5SDimitry Andric static_cast<size_t>(Options.MaxTotalTimeSec); 510b57cec5SDimitry Andric } 520b57cec5SDimitry Andric execPerSec()530b57cec5SDimitry Andric size_t execPerSec() { 540b57cec5SDimitry Andric size_t Seconds = secondsSinceProcessStartUp(); 550b57cec5SDimitry Andric return Seconds ? TotalNumberOfRuns / Seconds : 0; 560b57cec5SDimitry Andric } 570b57cec5SDimitry Andric getTotalNumberOfRuns()580b57cec5SDimitry Andric size_t getTotalNumberOfRuns() { return TotalNumberOfRuns; } 590b57cec5SDimitry Andric 600b57cec5SDimitry Andric static void StaticAlarmCallback(); 610b57cec5SDimitry Andric static void StaticCrashSignalCallback(); 620b57cec5SDimitry Andric static void StaticExitCallback(); 630b57cec5SDimitry Andric static void StaticInterruptCallback(); 640b57cec5SDimitry Andric static void StaticFileSizeExceedCallback(); 650b57cec5SDimitry Andric static void StaticGracefulExitCallback(); 660b57cec5SDimitry Andric 6781ad6265SDimitry Andric // Executes the target callback on {Data, Size} once. 6881ad6265SDimitry Andric // Returns false if the input was rejected by the target (target returned -1), 6981ad6265SDimitry Andric // and true otherwise. 7081ad6265SDimitry Andric bool ExecuteCallback(const uint8_t *Data, size_t Size); 710b57cec5SDimitry Andric bool RunOne(const uint8_t *Data, size_t Size, bool MayDeleteFile = false, 72e8d8bef9SDimitry Andric InputInfo *II = nullptr, bool ForceAddToCorpus = false, 73e8d8bef9SDimitry Andric bool *FoundUniqFeatures = nullptr); 74e8d8bef9SDimitry Andric void TPCUpdateObservedPCs(); 750b57cec5SDimitry Andric 760b57cec5SDimitry Andric // Merge Corpora[1:] into Corpora[0]. 77349cc55cSDimitry Andric void Merge(const std::vector<std::string> &Corpora); 78349cc55cSDimitry Andric void CrashResistantMergeInternalStep(const std::string &ControlFilePath, 79349cc55cSDimitry Andric bool IsSetCoverMerge); GetMD()800b57cec5SDimitry Andric MutationDispatcher &GetMD() { return MD; } 810b57cec5SDimitry Andric void PrintFinalStats(); 820b57cec5SDimitry Andric void SetMaxInputLen(size_t MaxInputLen); 830b57cec5SDimitry Andric void SetMaxMutationLen(size_t MaxMutationLen); 840b57cec5SDimitry Andric void RssLimitCallback(); 850b57cec5SDimitry Andric InFuzzingThread()860b57cec5SDimitry Andric bool InFuzzingThread() const { return IsMyThread; } 870b57cec5SDimitry Andric size_t GetCurrentUnitInFuzzingThead(const uint8_t **Data) const; 880b57cec5SDimitry Andric void TryDetectingAMemoryLeak(const uint8_t *Data, size_t Size, 890b57cec5SDimitry Andric bool DuringInitialCorpusExecution); 900b57cec5SDimitry Andric 910b57cec5SDimitry Andric void HandleMalloc(size_t Size); 920b57cec5SDimitry Andric static void MaybeExitGracefully(); 93bdd1243dSDimitry Andric static int InterruptExitCode(); 940b57cec5SDimitry Andric std::string WriteToOutputCorpus(const Unit &U); 950b57cec5SDimitry Andric 960b57cec5SDimitry Andric private: 970b57cec5SDimitry Andric void AlarmCallback(); 980b57cec5SDimitry Andric void CrashCallback(); 990b57cec5SDimitry Andric void ExitCallback(); 1000b57cec5SDimitry Andric void CrashOnOverwrittenData(); 1010b57cec5SDimitry Andric void InterruptCallback(); 1020b57cec5SDimitry Andric void MutateAndTestOne(); 1030b57cec5SDimitry Andric void PurgeAllocator(); 1040b57cec5SDimitry Andric void ReportNewCoverage(InputInfo *II, const Unit &U); 1050b57cec5SDimitry Andric void PrintPulseAndReportSlowInput(const uint8_t *Data, size_t Size); 1060b57cec5SDimitry Andric void WriteUnitToFileWithPrefix(const Unit &U, const char *Prefix); 10768d75effSDimitry Andric void PrintStats(const char *Where, const char *End = "\n", size_t Units = 0, 10868d75effSDimitry Andric size_t Features = 0); 1090b57cec5SDimitry Andric void PrintStatusForNewUnit(const Unit &U, const char *Text); 1100b57cec5SDimitry Andric void CheckExitOnSrcPosOrItem(); 1110b57cec5SDimitry Andric 1120b57cec5SDimitry Andric static void StaticDeathCallback(); 1130b57cec5SDimitry Andric void DumpCurrentUnit(const char *Prefix); 1140b57cec5SDimitry Andric void DeathCallback(); 1150b57cec5SDimitry Andric 1160b57cec5SDimitry Andric void AllocateCurrentUnitData(); 1170b57cec5SDimitry Andric uint8_t *CurrentUnitData = nullptr; 1180b57cec5SDimitry Andric std::atomic<size_t> CurrentUnitSize; 1190b57cec5SDimitry Andric uint8_t BaseSha1[kSHA1NumBytes]; // Checksum of the base unit. 1200b57cec5SDimitry Andric 1210b57cec5SDimitry Andric bool GracefulExitRequested = false; 1220b57cec5SDimitry Andric 1230b57cec5SDimitry Andric size_t TotalNumberOfRuns = 0; 1240b57cec5SDimitry Andric size_t NumberOfNewUnitsAdded = 0; 1250b57cec5SDimitry Andric 1260b57cec5SDimitry Andric size_t LastCorpusUpdateRun = 0; 1270b57cec5SDimitry Andric 1280b57cec5SDimitry Andric bool HasMoreMallocsThanFrees = false; 1290b57cec5SDimitry Andric size_t NumberOfLeakDetectionAttempts = 0; 1300b57cec5SDimitry Andric 1310b57cec5SDimitry Andric system_clock::time_point LastAllocatorPurgeAttemptTime = system_clock::now(); 1320b57cec5SDimitry Andric 1330b57cec5SDimitry Andric UserCallback CB; 1340b57cec5SDimitry Andric InputCorpus &Corpus; 1350b57cec5SDimitry Andric MutationDispatcher &MD; 1360b57cec5SDimitry Andric FuzzingOptions Options; 1370b57cec5SDimitry Andric DataFlowTrace DFT; 1380b57cec5SDimitry Andric 1390b57cec5SDimitry Andric system_clock::time_point ProcessStartTime = system_clock::now(); 1400b57cec5SDimitry Andric system_clock::time_point UnitStartTime, UnitStopTime; 1410b57cec5SDimitry Andric long TimeOfLongestUnitInSeconds = 0; 1420b57cec5SDimitry Andric long EpochOfLastReadOfOutputCorpus = 0; 1430b57cec5SDimitry Andric 1440b57cec5SDimitry Andric size_t MaxInputLen = 0; 1450b57cec5SDimitry Andric size_t MaxMutationLen = 0; 1460b57cec5SDimitry Andric size_t TmpMaxMutationLen = 0; 1470b57cec5SDimitry Andric 148349cc55cSDimitry Andric std::vector<uint32_t> UniqFeatureSetTmp; 1490b57cec5SDimitry Andric 1500b57cec5SDimitry Andric // Need to know our own thread. 1510b57cec5SDimitry Andric static thread_local bool IsMyThread; 1520b57cec5SDimitry Andric }; 1530b57cec5SDimitry Andric 1540b57cec5SDimitry Andric struct ScopedEnableMsanInterceptorChecks { ScopedEnableMsanInterceptorChecksScopedEnableMsanInterceptorChecks1550b57cec5SDimitry Andric ScopedEnableMsanInterceptorChecks() { 1560b57cec5SDimitry Andric if (EF->__msan_scoped_enable_interceptor_checks) 1570b57cec5SDimitry Andric EF->__msan_scoped_enable_interceptor_checks(); 1580b57cec5SDimitry Andric } ~ScopedEnableMsanInterceptorChecksScopedEnableMsanInterceptorChecks1590b57cec5SDimitry Andric ~ScopedEnableMsanInterceptorChecks() { 1600b57cec5SDimitry Andric if (EF->__msan_scoped_disable_interceptor_checks) 1610b57cec5SDimitry Andric EF->__msan_scoped_disable_interceptor_checks(); 1620b57cec5SDimitry Andric } 1630b57cec5SDimitry Andric }; 1640b57cec5SDimitry Andric 1650b57cec5SDimitry Andric struct ScopedDisableMsanInterceptorChecks { ScopedDisableMsanInterceptorChecksScopedDisableMsanInterceptorChecks1660b57cec5SDimitry Andric ScopedDisableMsanInterceptorChecks() { 1670b57cec5SDimitry Andric if (EF->__msan_scoped_disable_interceptor_checks) 1680b57cec5SDimitry Andric EF->__msan_scoped_disable_interceptor_checks(); 1690b57cec5SDimitry Andric } ~ScopedDisableMsanInterceptorChecksScopedDisableMsanInterceptorChecks1700b57cec5SDimitry Andric ~ScopedDisableMsanInterceptorChecks() { 1710b57cec5SDimitry Andric if (EF->__msan_scoped_enable_interceptor_checks) 1720b57cec5SDimitry Andric EF->__msan_scoped_enable_interceptor_checks(); 1730b57cec5SDimitry Andric } 1740b57cec5SDimitry Andric }; 1750b57cec5SDimitry Andric 1760b57cec5SDimitry Andric } // namespace fuzzer 1770b57cec5SDimitry Andric 1780b57cec5SDimitry Andric #endif // LLVM_FUZZER_INTERNAL_H 179