179 lines · c
1//===- FuzzerInternal.h - Internal header for the Fuzzer --------*- C++ -* ===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8// Define the main class fuzzer::Fuzzer and most functions.9//===----------------------------------------------------------------------===//10 11#ifndef LLVM_FUZZER_INTERNAL_H12#define LLVM_FUZZER_INTERNAL_H13 14#include "FuzzerDataFlowTrace.h"15#include "FuzzerDefs.h"16#include "FuzzerExtFunctions.h"17#include "FuzzerInterface.h"18#include "FuzzerOptions.h"19#include "FuzzerSHA1.h"20#include "FuzzerValueBitMap.h"21#include <algorithm>22#include <atomic>23#include <chrono>24#include <climits>25#include <cstdlib>26#include <string.h>27 28namespace fuzzer {29 30using namespace std::chrono;31 32class Fuzzer final {33public:34 Fuzzer(UserCallback CB, InputCorpus &Corpus, MutationDispatcher &MD,35 const FuzzingOptions &Options);36 ~Fuzzer() = delete;37 void Loop(std::vector<SizedFile> &CorporaFiles);38 void ReadAndExecuteSeedCorpora(std::vector<SizedFile> &CorporaFiles);39 void MinimizeCrashLoop(const Unit &U);40 void RereadOutputCorpus(size_t MaxSize);41 42 size_t secondsSinceProcessStartUp() {43 return duration_cast<seconds>(system_clock::now() - ProcessStartTime)44 .count();45 }46 47 bool TimedOut() {48 return Options.MaxTotalTimeSec > 0 &&49 secondsSinceProcessStartUp() >50 static_cast<size_t>(Options.MaxTotalTimeSec);51 }52 53 size_t execPerSec() {54 size_t Seconds = secondsSinceProcessStartUp();55 return Seconds ? TotalNumberOfRuns / Seconds : 0;56 }57 58 size_t getTotalNumberOfRuns() { return TotalNumberOfRuns; }59 60 static void StaticAlarmCallback();61 static void StaticCrashSignalCallback();62 static void StaticExitCallback();63 static void StaticInterruptCallback();64 static void StaticFileSizeExceedCallback();65 static void StaticGracefulExitCallback();66 67 // Executes the target callback on {Data, Size} once.68 // Returns false if the input was rejected by the target (target returned -1),69 // and true otherwise.70 bool ExecuteCallback(const uint8_t *Data, size_t Size);71 bool RunOne(const uint8_t *Data, size_t Size, bool MayDeleteFile = false,72 InputInfo *II = nullptr, bool ForceAddToCorpus = false,73 bool *FoundUniqFeatures = nullptr);74 void TPCUpdateObservedPCs();75 76 // Merge Corpora[1:] into Corpora[0].77 void Merge(const std::vector<std::string> &Corpora);78 void CrashResistantMergeInternalStep(const std::string &ControlFilePath,79 bool IsSetCoverMerge);80 MutationDispatcher &GetMD() { return MD; }81 void PrintFinalStats();82 void SetMaxInputLen(size_t MaxInputLen);83 void SetMaxMutationLen(size_t MaxMutationLen);84 void RssLimitCallback();85 86 bool InFuzzingThread() const { return IsMyThread; }87 size_t GetCurrentUnitInFuzzingThead(const uint8_t **Data) const;88 void TryDetectingAMemoryLeak(const uint8_t *Data, size_t Size,89 bool DuringInitialCorpusExecution);90 91 void HandleMalloc(size_t Size);92 static void MaybeExitGracefully();93 static int InterruptExitCode();94 std::string WriteToOutputCorpus(const Unit &U);95 96private:97 void AlarmCallback();98 void CrashCallback();99 void ExitCallback();100 void CrashOnOverwrittenData();101 void InterruptCallback();102 void MutateAndTestOne();103 void PurgeAllocator();104 void ReportNewCoverage(InputInfo *II, const Unit &U);105 void PrintPulseAndReportSlowInput(const uint8_t *Data, size_t Size);106 void WriteUnitToFileWithPrefix(const Unit &U, const char *Prefix);107 void PrintStats(const char *Where, const char *End = "\n", size_t Units = 0,108 size_t Features = 0);109 void PrintStatusForNewUnit(const Unit &U, const char *Text);110 void CheckExitOnSrcPosOrItem();111 112 static void StaticDeathCallback();113 void DumpCurrentUnit(const char *Prefix);114 void DeathCallback();115 116 void AllocateCurrentUnitData();117 uint8_t *CurrentUnitData = nullptr;118 std::atomic<size_t> CurrentUnitSize;119 uint8_t BaseSha1[kSHA1NumBytes]; // Checksum of the base unit.120 121 bool GracefulExitRequested = false;122 123 size_t TotalNumberOfRuns = 0;124 size_t NumberOfNewUnitsAdded = 0;125 126 size_t LastCorpusUpdateRun = 0;127 128 bool HasMoreMallocsThanFrees = false;129 size_t NumberOfLeakDetectionAttempts = 0;130 131 system_clock::time_point LastAllocatorPurgeAttemptTime = system_clock::now();132 133 UserCallback CB;134 InputCorpus &Corpus;135 MutationDispatcher &MD;136 FuzzingOptions Options;137 DataFlowTrace DFT;138 139 system_clock::time_point ProcessStartTime = system_clock::now();140 system_clock::time_point UnitStartTime, UnitStopTime;141 long TimeOfLongestUnitInSeconds = 0;142 long EpochOfLastReadOfOutputCorpus = 0;143 144 size_t MaxInputLen = 0;145 size_t MaxMutationLen = 0;146 size_t TmpMaxMutationLen = 0;147 148 std::vector<uint32_t> UniqFeatureSetTmp;149 150 // Need to know our own thread.151 static thread_local bool IsMyThread;152};153 154struct ScopedEnableMsanInterceptorChecks {155 ScopedEnableMsanInterceptorChecks() {156 if (EF->__msan_scoped_enable_interceptor_checks)157 EF->__msan_scoped_enable_interceptor_checks();158 }159 ~ScopedEnableMsanInterceptorChecks() {160 if (EF->__msan_scoped_disable_interceptor_checks)161 EF->__msan_scoped_disable_interceptor_checks();162 }163};164 165struct ScopedDisableMsanInterceptorChecks {166 ScopedDisableMsanInterceptorChecks() {167 if (EF->__msan_scoped_disable_interceptor_checks)168 EF->__msan_scoped_disable_interceptor_checks();169 }170 ~ScopedDisableMsanInterceptorChecks() {171 if (EF->__msan_scoped_enable_interceptor_checks)172 EF->__msan_scoped_enable_interceptor_checks();173 }174};175 176} // namespace fuzzer177 178#endif // LLVM_FUZZER_INTERNAL_H179