xref: /openbsd-src/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerInternal.h (revision 810390e339a5425391477d5d41c78d7cab2424ac)
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