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-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | // Define the main class fuzzer::Fuzzer and most functions. |
9 | //===----------------------------------------------------------------------===// |
10 | |
11 | #ifndef LLVM_FUZZER_INTERNAL_H |
12 | #define LLVM_FUZZER_INTERNAL_H |
13 | |
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 | |
28 | namespace fuzzer { |
29 | |
30 | using namespace std::chrono; |
31 | |
32 | class Fuzzer final { |
33 | public: |
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>(d: 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 (); |
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 | |
96 | private: |
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 | |
154 | struct 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 | |
165 | struct 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 fuzzer |
177 | |
178 | #endif // LLVM_FUZZER_INTERNAL_H |
179 | |