xref: /freebsd/contrib/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp (revision 0b57cec536236d46e3dba9bd041533462f33dbb7)
1*0b57cec5SDimitry Andric //===- FuzzerLoop.cpp - Fuzzer's main loop --------------------------------===//
2*0b57cec5SDimitry Andric //
3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*0b57cec5SDimitry Andric //
7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
8*0b57cec5SDimitry Andric // Fuzzer's main loop.
9*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
10*0b57cec5SDimitry Andric 
11*0b57cec5SDimitry Andric #include "FuzzerCorpus.h"
12*0b57cec5SDimitry Andric #include "FuzzerIO.h"
13*0b57cec5SDimitry Andric #include "FuzzerInternal.h"
14*0b57cec5SDimitry Andric #include "FuzzerMutate.h"
15*0b57cec5SDimitry Andric #include "FuzzerRandom.h"
16*0b57cec5SDimitry Andric #include "FuzzerTracePC.h"
17*0b57cec5SDimitry Andric #include <algorithm>
18*0b57cec5SDimitry Andric #include <cstring>
19*0b57cec5SDimitry Andric #include <memory>
20*0b57cec5SDimitry Andric #include <mutex>
21*0b57cec5SDimitry Andric #include <set>
22*0b57cec5SDimitry Andric 
23*0b57cec5SDimitry Andric #if defined(__has_include)
24*0b57cec5SDimitry Andric #if __has_include(<sanitizer / lsan_interface.h>)
25*0b57cec5SDimitry Andric #include <sanitizer/lsan_interface.h>
26*0b57cec5SDimitry Andric #endif
27*0b57cec5SDimitry Andric #endif
28*0b57cec5SDimitry Andric 
29*0b57cec5SDimitry Andric #define NO_SANITIZE_MEMORY
30*0b57cec5SDimitry Andric #if defined(__has_feature)
31*0b57cec5SDimitry Andric #if __has_feature(memory_sanitizer)
32*0b57cec5SDimitry Andric #undef NO_SANITIZE_MEMORY
33*0b57cec5SDimitry Andric #define NO_SANITIZE_MEMORY __attribute__((no_sanitize_memory))
34*0b57cec5SDimitry Andric #endif
35*0b57cec5SDimitry Andric #endif
36*0b57cec5SDimitry Andric 
37*0b57cec5SDimitry Andric namespace fuzzer {
38*0b57cec5SDimitry Andric static const size_t kMaxUnitSizeToPrint = 256;
39*0b57cec5SDimitry Andric 
40*0b57cec5SDimitry Andric thread_local bool Fuzzer::IsMyThread;
41*0b57cec5SDimitry Andric 
42*0b57cec5SDimitry Andric bool RunningUserCallback = false;
43*0b57cec5SDimitry Andric 
44*0b57cec5SDimitry Andric // Only one Fuzzer per process.
45*0b57cec5SDimitry Andric static Fuzzer *F;
46*0b57cec5SDimitry Andric 
47*0b57cec5SDimitry Andric // Leak detection is expensive, so we first check if there were more mallocs
48*0b57cec5SDimitry Andric // than frees (using the sanitizer malloc hooks) and only then try to call lsan.
49*0b57cec5SDimitry Andric struct MallocFreeTracer {
50*0b57cec5SDimitry Andric   void Start(int TraceLevel) {
51*0b57cec5SDimitry Andric     this->TraceLevel = TraceLevel;
52*0b57cec5SDimitry Andric     if (TraceLevel)
53*0b57cec5SDimitry Andric       Printf("MallocFreeTracer: START\n");
54*0b57cec5SDimitry Andric     Mallocs = 0;
55*0b57cec5SDimitry Andric     Frees = 0;
56*0b57cec5SDimitry Andric   }
57*0b57cec5SDimitry Andric   // Returns true if there were more mallocs than frees.
58*0b57cec5SDimitry Andric   bool Stop() {
59*0b57cec5SDimitry Andric     if (TraceLevel)
60*0b57cec5SDimitry Andric       Printf("MallocFreeTracer: STOP %zd %zd (%s)\n", Mallocs.load(),
61*0b57cec5SDimitry Andric              Frees.load(), Mallocs == Frees ? "same" : "DIFFERENT");
62*0b57cec5SDimitry Andric     bool Result = Mallocs > Frees;
63*0b57cec5SDimitry Andric     Mallocs = 0;
64*0b57cec5SDimitry Andric     Frees = 0;
65*0b57cec5SDimitry Andric     TraceLevel = 0;
66*0b57cec5SDimitry Andric     return Result;
67*0b57cec5SDimitry Andric   }
68*0b57cec5SDimitry Andric   std::atomic<size_t> Mallocs;
69*0b57cec5SDimitry Andric   std::atomic<size_t> Frees;
70*0b57cec5SDimitry Andric   int TraceLevel = 0;
71*0b57cec5SDimitry Andric 
72*0b57cec5SDimitry Andric   std::recursive_mutex TraceMutex;
73*0b57cec5SDimitry Andric   bool TraceDisabled = false;
74*0b57cec5SDimitry Andric };
75*0b57cec5SDimitry Andric 
76*0b57cec5SDimitry Andric static MallocFreeTracer AllocTracer;
77*0b57cec5SDimitry Andric 
78*0b57cec5SDimitry Andric // Locks printing and avoids nested hooks triggered from mallocs/frees in
79*0b57cec5SDimitry Andric // sanitizer.
80*0b57cec5SDimitry Andric class TraceLock {
81*0b57cec5SDimitry Andric public:
82*0b57cec5SDimitry Andric   TraceLock() : Lock(AllocTracer.TraceMutex) {
83*0b57cec5SDimitry Andric     AllocTracer.TraceDisabled = !AllocTracer.TraceDisabled;
84*0b57cec5SDimitry Andric   }
85*0b57cec5SDimitry Andric   ~TraceLock() { AllocTracer.TraceDisabled = !AllocTracer.TraceDisabled; }
86*0b57cec5SDimitry Andric 
87*0b57cec5SDimitry Andric   bool IsDisabled() const {
88*0b57cec5SDimitry Andric     // This is already inverted value.
89*0b57cec5SDimitry Andric     return !AllocTracer.TraceDisabled;
90*0b57cec5SDimitry Andric   }
91*0b57cec5SDimitry Andric 
92*0b57cec5SDimitry Andric private:
93*0b57cec5SDimitry Andric   std::lock_guard<std::recursive_mutex> Lock;
94*0b57cec5SDimitry Andric };
95*0b57cec5SDimitry Andric 
96*0b57cec5SDimitry Andric ATTRIBUTE_NO_SANITIZE_MEMORY
97*0b57cec5SDimitry Andric void MallocHook(const volatile void *ptr, size_t size) {
98*0b57cec5SDimitry Andric   size_t N = AllocTracer.Mallocs++;
99*0b57cec5SDimitry Andric   F->HandleMalloc(size);
100*0b57cec5SDimitry Andric   if (int TraceLevel = AllocTracer.TraceLevel) {
101*0b57cec5SDimitry Andric     TraceLock Lock;
102*0b57cec5SDimitry Andric     if (Lock.IsDisabled())
103*0b57cec5SDimitry Andric       return;
104*0b57cec5SDimitry Andric     Printf("MALLOC[%zd] %p %zd\n", N, ptr, size);
105*0b57cec5SDimitry Andric     if (TraceLevel >= 2 && EF)
106*0b57cec5SDimitry Andric       PrintStackTrace();
107*0b57cec5SDimitry Andric   }
108*0b57cec5SDimitry Andric }
109*0b57cec5SDimitry Andric 
110*0b57cec5SDimitry Andric ATTRIBUTE_NO_SANITIZE_MEMORY
111*0b57cec5SDimitry Andric void FreeHook(const volatile void *ptr) {
112*0b57cec5SDimitry Andric   size_t N = AllocTracer.Frees++;
113*0b57cec5SDimitry Andric   if (int TraceLevel = AllocTracer.TraceLevel) {
114*0b57cec5SDimitry Andric     TraceLock Lock;
115*0b57cec5SDimitry Andric     if (Lock.IsDisabled())
116*0b57cec5SDimitry Andric       return;
117*0b57cec5SDimitry Andric     Printf("FREE[%zd]   %p\n", N, ptr);
118*0b57cec5SDimitry Andric     if (TraceLevel >= 2 && EF)
119*0b57cec5SDimitry Andric       PrintStackTrace();
120*0b57cec5SDimitry Andric   }
121*0b57cec5SDimitry Andric }
122*0b57cec5SDimitry Andric 
123*0b57cec5SDimitry Andric // Crash on a single malloc that exceeds the rss limit.
124*0b57cec5SDimitry Andric void Fuzzer::HandleMalloc(size_t Size) {
125*0b57cec5SDimitry Andric   if (!Options.MallocLimitMb || (Size >> 20) < (size_t)Options.MallocLimitMb)
126*0b57cec5SDimitry Andric     return;
127*0b57cec5SDimitry Andric   Printf("==%d== ERROR: libFuzzer: out-of-memory (malloc(%zd))\n", GetPid(),
128*0b57cec5SDimitry Andric          Size);
129*0b57cec5SDimitry Andric   Printf("   To change the out-of-memory limit use -rss_limit_mb=<N>\n\n");
130*0b57cec5SDimitry Andric   PrintStackTrace();
131*0b57cec5SDimitry Andric   DumpCurrentUnit("oom-");
132*0b57cec5SDimitry Andric   Printf("SUMMARY: libFuzzer: out-of-memory\n");
133*0b57cec5SDimitry Andric   PrintFinalStats();
134*0b57cec5SDimitry Andric   _Exit(Options.OOMExitCode); // Stop right now.
135*0b57cec5SDimitry Andric }
136*0b57cec5SDimitry Andric 
137*0b57cec5SDimitry Andric Fuzzer::Fuzzer(UserCallback CB, InputCorpus &Corpus, MutationDispatcher &MD,
138*0b57cec5SDimitry Andric                FuzzingOptions Options)
139*0b57cec5SDimitry Andric     : CB(CB), Corpus(Corpus), MD(MD), Options(Options) {
140*0b57cec5SDimitry Andric   if (EF->__sanitizer_set_death_callback)
141*0b57cec5SDimitry Andric     EF->__sanitizer_set_death_callback(StaticDeathCallback);
142*0b57cec5SDimitry Andric   assert(!F);
143*0b57cec5SDimitry Andric   F = this;
144*0b57cec5SDimitry Andric   TPC.ResetMaps();
145*0b57cec5SDimitry Andric   IsMyThread = true;
146*0b57cec5SDimitry Andric   if (Options.DetectLeaks && EF->__sanitizer_install_malloc_and_free_hooks)
147*0b57cec5SDimitry Andric     EF->__sanitizer_install_malloc_and_free_hooks(MallocHook, FreeHook);
148*0b57cec5SDimitry Andric   TPC.SetUseCounters(Options.UseCounters);
149*0b57cec5SDimitry Andric   TPC.SetUseValueProfileMask(Options.UseValueProfile);
150*0b57cec5SDimitry Andric 
151*0b57cec5SDimitry Andric   if (Options.Verbosity)
152*0b57cec5SDimitry Andric     TPC.PrintModuleInfo();
153*0b57cec5SDimitry Andric   if (!Options.OutputCorpus.empty() && Options.ReloadIntervalSec)
154*0b57cec5SDimitry Andric     EpochOfLastReadOfOutputCorpus = GetEpoch(Options.OutputCorpus);
155*0b57cec5SDimitry Andric   MaxInputLen = MaxMutationLen = Options.MaxLen;
156*0b57cec5SDimitry Andric   TmpMaxMutationLen = 0;  // Will be set once we load the corpus.
157*0b57cec5SDimitry Andric   AllocateCurrentUnitData();
158*0b57cec5SDimitry Andric   CurrentUnitSize = 0;
159*0b57cec5SDimitry Andric   memset(BaseSha1, 0, sizeof(BaseSha1));
160*0b57cec5SDimitry Andric }
161*0b57cec5SDimitry Andric 
162*0b57cec5SDimitry Andric Fuzzer::~Fuzzer() {}
163*0b57cec5SDimitry Andric 
164*0b57cec5SDimitry Andric void Fuzzer::AllocateCurrentUnitData() {
165*0b57cec5SDimitry Andric   if (CurrentUnitData || MaxInputLen == 0)
166*0b57cec5SDimitry Andric     return;
167*0b57cec5SDimitry Andric   CurrentUnitData = new uint8_t[MaxInputLen];
168*0b57cec5SDimitry Andric }
169*0b57cec5SDimitry Andric 
170*0b57cec5SDimitry Andric void Fuzzer::StaticDeathCallback() {
171*0b57cec5SDimitry Andric   assert(F);
172*0b57cec5SDimitry Andric   F->DeathCallback();
173*0b57cec5SDimitry Andric }
174*0b57cec5SDimitry Andric 
175*0b57cec5SDimitry Andric void Fuzzer::DumpCurrentUnit(const char *Prefix) {
176*0b57cec5SDimitry Andric   if (!CurrentUnitData)
177*0b57cec5SDimitry Andric     return; // Happens when running individual inputs.
178*0b57cec5SDimitry Andric   ScopedDisableMsanInterceptorChecks S;
179*0b57cec5SDimitry Andric   MD.PrintMutationSequence();
180*0b57cec5SDimitry Andric   Printf("; base unit: %s\n", Sha1ToString(BaseSha1).c_str());
181*0b57cec5SDimitry Andric   size_t UnitSize = CurrentUnitSize;
182*0b57cec5SDimitry Andric   if (UnitSize <= kMaxUnitSizeToPrint) {
183*0b57cec5SDimitry Andric     PrintHexArray(CurrentUnitData, UnitSize, "\n");
184*0b57cec5SDimitry Andric     PrintASCII(CurrentUnitData, UnitSize, "\n");
185*0b57cec5SDimitry Andric   }
186*0b57cec5SDimitry Andric   WriteUnitToFileWithPrefix({CurrentUnitData, CurrentUnitData + UnitSize},
187*0b57cec5SDimitry Andric                             Prefix);
188*0b57cec5SDimitry Andric }
189*0b57cec5SDimitry Andric 
190*0b57cec5SDimitry Andric NO_SANITIZE_MEMORY
191*0b57cec5SDimitry Andric void Fuzzer::DeathCallback() {
192*0b57cec5SDimitry Andric   DumpCurrentUnit("crash-");
193*0b57cec5SDimitry Andric   PrintFinalStats();
194*0b57cec5SDimitry Andric }
195*0b57cec5SDimitry Andric 
196*0b57cec5SDimitry Andric void Fuzzer::StaticAlarmCallback() {
197*0b57cec5SDimitry Andric   assert(F);
198*0b57cec5SDimitry Andric   F->AlarmCallback();
199*0b57cec5SDimitry Andric }
200*0b57cec5SDimitry Andric 
201*0b57cec5SDimitry Andric void Fuzzer::StaticCrashSignalCallback() {
202*0b57cec5SDimitry Andric   assert(F);
203*0b57cec5SDimitry Andric   F->CrashCallback();
204*0b57cec5SDimitry Andric }
205*0b57cec5SDimitry Andric 
206*0b57cec5SDimitry Andric void Fuzzer::StaticExitCallback() {
207*0b57cec5SDimitry Andric   assert(F);
208*0b57cec5SDimitry Andric   F->ExitCallback();
209*0b57cec5SDimitry Andric }
210*0b57cec5SDimitry Andric 
211*0b57cec5SDimitry Andric void Fuzzer::StaticInterruptCallback() {
212*0b57cec5SDimitry Andric   assert(F);
213*0b57cec5SDimitry Andric   F->InterruptCallback();
214*0b57cec5SDimitry Andric }
215*0b57cec5SDimitry Andric 
216*0b57cec5SDimitry Andric void Fuzzer::StaticGracefulExitCallback() {
217*0b57cec5SDimitry Andric   assert(F);
218*0b57cec5SDimitry Andric   F->GracefulExitRequested = true;
219*0b57cec5SDimitry Andric   Printf("INFO: signal received, trying to exit gracefully\n");
220*0b57cec5SDimitry Andric }
221*0b57cec5SDimitry Andric 
222*0b57cec5SDimitry Andric void Fuzzer::StaticFileSizeExceedCallback() {
223*0b57cec5SDimitry Andric   Printf("==%lu== ERROR: libFuzzer: file size exceeded\n", GetPid());
224*0b57cec5SDimitry Andric   exit(1);
225*0b57cec5SDimitry Andric }
226*0b57cec5SDimitry Andric 
227*0b57cec5SDimitry Andric void Fuzzer::CrashCallback() {
228*0b57cec5SDimitry Andric   if (EF->__sanitizer_acquire_crash_state &&
229*0b57cec5SDimitry Andric       !EF->__sanitizer_acquire_crash_state())
230*0b57cec5SDimitry Andric     return;
231*0b57cec5SDimitry Andric   Printf("==%lu== ERROR: libFuzzer: deadly signal\n", GetPid());
232*0b57cec5SDimitry Andric   PrintStackTrace();
233*0b57cec5SDimitry Andric   Printf("NOTE: libFuzzer has rudimentary signal handlers.\n"
234*0b57cec5SDimitry Andric          "      Combine libFuzzer with AddressSanitizer or similar for better "
235*0b57cec5SDimitry Andric          "crash reports.\n");
236*0b57cec5SDimitry Andric   Printf("SUMMARY: libFuzzer: deadly signal\n");
237*0b57cec5SDimitry Andric   DumpCurrentUnit("crash-");
238*0b57cec5SDimitry Andric   PrintFinalStats();
239*0b57cec5SDimitry Andric   _Exit(Options.ErrorExitCode); // Stop right now.
240*0b57cec5SDimitry Andric }
241*0b57cec5SDimitry Andric 
242*0b57cec5SDimitry Andric void Fuzzer::ExitCallback() {
243*0b57cec5SDimitry Andric   if (!RunningUserCallback)
244*0b57cec5SDimitry Andric     return; // This exit did not come from the user callback
245*0b57cec5SDimitry Andric   if (EF->__sanitizer_acquire_crash_state &&
246*0b57cec5SDimitry Andric       !EF->__sanitizer_acquire_crash_state())
247*0b57cec5SDimitry Andric     return;
248*0b57cec5SDimitry Andric   Printf("==%lu== ERROR: libFuzzer: fuzz target exited\n", GetPid());
249*0b57cec5SDimitry Andric   PrintStackTrace();
250*0b57cec5SDimitry Andric   Printf("SUMMARY: libFuzzer: fuzz target exited\n");
251*0b57cec5SDimitry Andric   DumpCurrentUnit("crash-");
252*0b57cec5SDimitry Andric   PrintFinalStats();
253*0b57cec5SDimitry Andric   _Exit(Options.ErrorExitCode);
254*0b57cec5SDimitry Andric }
255*0b57cec5SDimitry Andric 
256*0b57cec5SDimitry Andric void Fuzzer::MaybeExitGracefully() {
257*0b57cec5SDimitry Andric   if (!F->GracefulExitRequested) return;
258*0b57cec5SDimitry Andric   Printf("==%lu== INFO: libFuzzer: exiting as requested\n", GetPid());
259*0b57cec5SDimitry Andric   RmDirRecursive(TempPath(".dir"));
260*0b57cec5SDimitry Andric   F->PrintFinalStats();
261*0b57cec5SDimitry Andric   _Exit(0);
262*0b57cec5SDimitry Andric }
263*0b57cec5SDimitry Andric 
264*0b57cec5SDimitry Andric void Fuzzer::InterruptCallback() {
265*0b57cec5SDimitry Andric   Printf("==%lu== libFuzzer: run interrupted; exiting\n", GetPid());
266*0b57cec5SDimitry Andric   PrintFinalStats();
267*0b57cec5SDimitry Andric   ScopedDisableMsanInterceptorChecks S; // RmDirRecursive may call opendir().
268*0b57cec5SDimitry Andric   RmDirRecursive(TempPath(".dir"));
269*0b57cec5SDimitry Andric   // Stop right now, don't perform any at-exit actions.
270*0b57cec5SDimitry Andric   _Exit(Options.InterruptExitCode);
271*0b57cec5SDimitry Andric }
272*0b57cec5SDimitry Andric 
273*0b57cec5SDimitry Andric NO_SANITIZE_MEMORY
274*0b57cec5SDimitry Andric void Fuzzer::AlarmCallback() {
275*0b57cec5SDimitry Andric   assert(Options.UnitTimeoutSec > 0);
276*0b57cec5SDimitry Andric   // In Windows Alarm callback is executed by a different thread.
277*0b57cec5SDimitry Andric   // NetBSD's current behavior needs this change too.
278*0b57cec5SDimitry Andric #if !LIBFUZZER_WINDOWS && !LIBFUZZER_NETBSD
279*0b57cec5SDimitry Andric   if (!InFuzzingThread())
280*0b57cec5SDimitry Andric     return;
281*0b57cec5SDimitry Andric #endif
282*0b57cec5SDimitry Andric   if (!RunningUserCallback)
283*0b57cec5SDimitry Andric     return; // We have not started running units yet.
284*0b57cec5SDimitry Andric   size_t Seconds =
285*0b57cec5SDimitry Andric       duration_cast<seconds>(system_clock::now() - UnitStartTime).count();
286*0b57cec5SDimitry Andric   if (Seconds == 0)
287*0b57cec5SDimitry Andric     return;
288*0b57cec5SDimitry Andric   if (Options.Verbosity >= 2)
289*0b57cec5SDimitry Andric     Printf("AlarmCallback %zd\n", Seconds);
290*0b57cec5SDimitry Andric   if (Seconds >= (size_t)Options.UnitTimeoutSec) {
291*0b57cec5SDimitry Andric     if (EF->__sanitizer_acquire_crash_state &&
292*0b57cec5SDimitry Andric         !EF->__sanitizer_acquire_crash_state())
293*0b57cec5SDimitry Andric       return;
294*0b57cec5SDimitry Andric     Printf("ALARM: working on the last Unit for %zd seconds\n", Seconds);
295*0b57cec5SDimitry Andric     Printf("       and the timeout value is %d (use -timeout=N to change)\n",
296*0b57cec5SDimitry Andric            Options.UnitTimeoutSec);
297*0b57cec5SDimitry Andric     DumpCurrentUnit("timeout-");
298*0b57cec5SDimitry Andric     Printf("==%lu== ERROR: libFuzzer: timeout after %d seconds\n", GetPid(),
299*0b57cec5SDimitry Andric            Seconds);
300*0b57cec5SDimitry Andric     PrintStackTrace();
301*0b57cec5SDimitry Andric     Printf("SUMMARY: libFuzzer: timeout\n");
302*0b57cec5SDimitry Andric     PrintFinalStats();
303*0b57cec5SDimitry Andric     _Exit(Options.TimeoutExitCode); // Stop right now.
304*0b57cec5SDimitry Andric   }
305*0b57cec5SDimitry Andric }
306*0b57cec5SDimitry Andric 
307*0b57cec5SDimitry Andric void Fuzzer::RssLimitCallback() {
308*0b57cec5SDimitry Andric   if (EF->__sanitizer_acquire_crash_state &&
309*0b57cec5SDimitry Andric       !EF->__sanitizer_acquire_crash_state())
310*0b57cec5SDimitry Andric     return;
311*0b57cec5SDimitry Andric   Printf(
312*0b57cec5SDimitry Andric       "==%lu== ERROR: libFuzzer: out-of-memory (used: %zdMb; limit: %zdMb)\n",
313*0b57cec5SDimitry Andric       GetPid(), GetPeakRSSMb(), Options.RssLimitMb);
314*0b57cec5SDimitry Andric   Printf("   To change the out-of-memory limit use -rss_limit_mb=<N>\n\n");
315*0b57cec5SDimitry Andric   PrintMemoryProfile();
316*0b57cec5SDimitry Andric   DumpCurrentUnit("oom-");
317*0b57cec5SDimitry Andric   Printf("SUMMARY: libFuzzer: out-of-memory\n");
318*0b57cec5SDimitry Andric   PrintFinalStats();
319*0b57cec5SDimitry Andric   _Exit(Options.OOMExitCode); // Stop right now.
320*0b57cec5SDimitry Andric }
321*0b57cec5SDimitry Andric 
322*0b57cec5SDimitry Andric void Fuzzer::PrintStats(const char *Where, const char *End, size_t Units) {
323*0b57cec5SDimitry Andric   size_t ExecPerSec = execPerSec();
324*0b57cec5SDimitry Andric   if (!Options.Verbosity)
325*0b57cec5SDimitry Andric     return;
326*0b57cec5SDimitry Andric   Printf("#%zd\t%s", TotalNumberOfRuns, Where);
327*0b57cec5SDimitry Andric   if (size_t N = TPC.GetTotalPCCoverage())
328*0b57cec5SDimitry Andric     Printf(" cov: %zd", N);
329*0b57cec5SDimitry Andric   if (size_t N = Corpus.NumFeatures())
330*0b57cec5SDimitry Andric     Printf(" ft: %zd", N);
331*0b57cec5SDimitry Andric   if (!Corpus.empty()) {
332*0b57cec5SDimitry Andric     Printf(" corp: %zd", Corpus.NumActiveUnits());
333*0b57cec5SDimitry Andric     if (size_t N = Corpus.SizeInBytes()) {
334*0b57cec5SDimitry Andric       if (N < (1 << 14))
335*0b57cec5SDimitry Andric         Printf("/%zdb", N);
336*0b57cec5SDimitry Andric       else if (N < (1 << 24))
337*0b57cec5SDimitry Andric         Printf("/%zdKb", N >> 10);
338*0b57cec5SDimitry Andric       else
339*0b57cec5SDimitry Andric         Printf("/%zdMb", N >> 20);
340*0b57cec5SDimitry Andric     }
341*0b57cec5SDimitry Andric     if (size_t FF = Corpus.NumInputsThatTouchFocusFunction())
342*0b57cec5SDimitry Andric       Printf(" focus: %zd", FF);
343*0b57cec5SDimitry Andric   }
344*0b57cec5SDimitry Andric   if (TmpMaxMutationLen)
345*0b57cec5SDimitry Andric     Printf(" lim: %zd", TmpMaxMutationLen);
346*0b57cec5SDimitry Andric   if (Units)
347*0b57cec5SDimitry Andric     Printf(" units: %zd", Units);
348*0b57cec5SDimitry Andric 
349*0b57cec5SDimitry Andric   Printf(" exec/s: %zd", ExecPerSec);
350*0b57cec5SDimitry Andric   Printf(" rss: %zdMb", GetPeakRSSMb());
351*0b57cec5SDimitry Andric   Printf("%s", End);
352*0b57cec5SDimitry Andric }
353*0b57cec5SDimitry Andric 
354*0b57cec5SDimitry Andric void Fuzzer::PrintFinalStats() {
355*0b57cec5SDimitry Andric   if (Options.PrintCoverage)
356*0b57cec5SDimitry Andric     TPC.PrintCoverage();
357*0b57cec5SDimitry Andric   if (Options.PrintCorpusStats)
358*0b57cec5SDimitry Andric     Corpus.PrintStats();
359*0b57cec5SDimitry Andric   if (!Options.PrintFinalStats)
360*0b57cec5SDimitry Andric     return;
361*0b57cec5SDimitry Andric   size_t ExecPerSec = execPerSec();
362*0b57cec5SDimitry Andric   Printf("stat::number_of_executed_units: %zd\n", TotalNumberOfRuns);
363*0b57cec5SDimitry Andric   Printf("stat::average_exec_per_sec:     %zd\n", ExecPerSec);
364*0b57cec5SDimitry Andric   Printf("stat::new_units_added:          %zd\n", NumberOfNewUnitsAdded);
365*0b57cec5SDimitry Andric   Printf("stat::slowest_unit_time_sec:    %zd\n", TimeOfLongestUnitInSeconds);
366*0b57cec5SDimitry Andric   Printf("stat::peak_rss_mb:              %zd\n", GetPeakRSSMb());
367*0b57cec5SDimitry Andric }
368*0b57cec5SDimitry Andric 
369*0b57cec5SDimitry Andric void Fuzzer::SetMaxInputLen(size_t MaxInputLen) {
370*0b57cec5SDimitry Andric   assert(this->MaxInputLen == 0); // Can only reset MaxInputLen from 0 to non-0.
371*0b57cec5SDimitry Andric   assert(MaxInputLen);
372*0b57cec5SDimitry Andric   this->MaxInputLen = MaxInputLen;
373*0b57cec5SDimitry Andric   this->MaxMutationLen = MaxInputLen;
374*0b57cec5SDimitry Andric   AllocateCurrentUnitData();
375*0b57cec5SDimitry Andric   Printf("INFO: -max_len is not provided; "
376*0b57cec5SDimitry Andric          "libFuzzer will not generate inputs larger than %zd bytes\n",
377*0b57cec5SDimitry Andric          MaxInputLen);
378*0b57cec5SDimitry Andric }
379*0b57cec5SDimitry Andric 
380*0b57cec5SDimitry Andric void Fuzzer::SetMaxMutationLen(size_t MaxMutationLen) {
381*0b57cec5SDimitry Andric   assert(MaxMutationLen && MaxMutationLen <= MaxInputLen);
382*0b57cec5SDimitry Andric   this->MaxMutationLen = MaxMutationLen;
383*0b57cec5SDimitry Andric }
384*0b57cec5SDimitry Andric 
385*0b57cec5SDimitry Andric void Fuzzer::CheckExitOnSrcPosOrItem() {
386*0b57cec5SDimitry Andric   if (!Options.ExitOnSrcPos.empty()) {
387*0b57cec5SDimitry Andric     static auto *PCsSet = new Set<uintptr_t>;
388*0b57cec5SDimitry Andric     auto HandlePC = [&](const TracePC::PCTableEntry *TE) {
389*0b57cec5SDimitry Andric       if (!PCsSet->insert(TE->PC).second)
390*0b57cec5SDimitry Andric         return;
391*0b57cec5SDimitry Andric       std::string Descr = DescribePC("%F %L", TE->PC + 1);
392*0b57cec5SDimitry Andric       if (Descr.find(Options.ExitOnSrcPos) != std::string::npos) {
393*0b57cec5SDimitry Andric         Printf("INFO: found line matching '%s', exiting.\n",
394*0b57cec5SDimitry Andric                Options.ExitOnSrcPos.c_str());
395*0b57cec5SDimitry Andric         _Exit(0);
396*0b57cec5SDimitry Andric       }
397*0b57cec5SDimitry Andric     };
398*0b57cec5SDimitry Andric     TPC.ForEachObservedPC(HandlePC);
399*0b57cec5SDimitry Andric   }
400*0b57cec5SDimitry Andric   if (!Options.ExitOnItem.empty()) {
401*0b57cec5SDimitry Andric     if (Corpus.HasUnit(Options.ExitOnItem)) {
402*0b57cec5SDimitry Andric       Printf("INFO: found item with checksum '%s', exiting.\n",
403*0b57cec5SDimitry Andric              Options.ExitOnItem.c_str());
404*0b57cec5SDimitry Andric       _Exit(0);
405*0b57cec5SDimitry Andric     }
406*0b57cec5SDimitry Andric   }
407*0b57cec5SDimitry Andric }
408*0b57cec5SDimitry Andric 
409*0b57cec5SDimitry Andric void Fuzzer::RereadOutputCorpus(size_t MaxSize) {
410*0b57cec5SDimitry Andric   if (Options.OutputCorpus.empty() || !Options.ReloadIntervalSec)
411*0b57cec5SDimitry Andric     return;
412*0b57cec5SDimitry Andric   Vector<Unit> AdditionalCorpus;
413*0b57cec5SDimitry Andric   ReadDirToVectorOfUnits(Options.OutputCorpus.c_str(), &AdditionalCorpus,
414*0b57cec5SDimitry Andric                          &EpochOfLastReadOfOutputCorpus, MaxSize,
415*0b57cec5SDimitry Andric                          /*ExitOnError*/ false);
416*0b57cec5SDimitry Andric   if (Options.Verbosity >= 2)
417*0b57cec5SDimitry Andric     Printf("Reload: read %zd new units.\n", AdditionalCorpus.size());
418*0b57cec5SDimitry Andric   bool Reloaded = false;
419*0b57cec5SDimitry Andric   for (auto &U : AdditionalCorpus) {
420*0b57cec5SDimitry Andric     if (U.size() > MaxSize)
421*0b57cec5SDimitry Andric       U.resize(MaxSize);
422*0b57cec5SDimitry Andric     if (!Corpus.HasUnit(U)) {
423*0b57cec5SDimitry Andric       if (RunOne(U.data(), U.size())) {
424*0b57cec5SDimitry Andric         CheckExitOnSrcPosOrItem();
425*0b57cec5SDimitry Andric         Reloaded = true;
426*0b57cec5SDimitry Andric       }
427*0b57cec5SDimitry Andric     }
428*0b57cec5SDimitry Andric   }
429*0b57cec5SDimitry Andric   if (Reloaded)
430*0b57cec5SDimitry Andric     PrintStats("RELOAD");
431*0b57cec5SDimitry Andric }
432*0b57cec5SDimitry Andric 
433*0b57cec5SDimitry Andric void Fuzzer::PrintPulseAndReportSlowInput(const uint8_t *Data, size_t Size) {
434*0b57cec5SDimitry Andric   auto TimeOfUnit =
435*0b57cec5SDimitry Andric       duration_cast<seconds>(UnitStopTime - UnitStartTime).count();
436*0b57cec5SDimitry Andric   if (!(TotalNumberOfRuns & (TotalNumberOfRuns - 1)) &&
437*0b57cec5SDimitry Andric       secondsSinceProcessStartUp() >= 2)
438*0b57cec5SDimitry Andric     PrintStats("pulse ");
439*0b57cec5SDimitry Andric   if (TimeOfUnit > TimeOfLongestUnitInSeconds * 1.1 &&
440*0b57cec5SDimitry Andric       TimeOfUnit >= Options.ReportSlowUnits) {
441*0b57cec5SDimitry Andric     TimeOfLongestUnitInSeconds = TimeOfUnit;
442*0b57cec5SDimitry Andric     Printf("Slowest unit: %zd s:\n", TimeOfLongestUnitInSeconds);
443*0b57cec5SDimitry Andric     WriteUnitToFileWithPrefix({Data, Data + Size}, "slow-unit-");
444*0b57cec5SDimitry Andric   }
445*0b57cec5SDimitry Andric }
446*0b57cec5SDimitry Andric 
447*0b57cec5SDimitry Andric static void WriteFeatureSetToFile(const std::string &FeaturesDir,
448*0b57cec5SDimitry Andric                                   const std::string &FileName,
449*0b57cec5SDimitry Andric                                   const Vector<uint32_t> &FeatureSet) {
450*0b57cec5SDimitry Andric   if (FeaturesDir.empty() || FeatureSet.empty()) return;
451*0b57cec5SDimitry Andric   WriteToFile(reinterpret_cast<const uint8_t *>(FeatureSet.data()),
452*0b57cec5SDimitry Andric               FeatureSet.size() * sizeof(FeatureSet[0]),
453*0b57cec5SDimitry Andric               DirPlusFile(FeaturesDir, FileName));
454*0b57cec5SDimitry Andric }
455*0b57cec5SDimitry Andric 
456*0b57cec5SDimitry Andric static void RenameFeatureSetFile(const std::string &FeaturesDir,
457*0b57cec5SDimitry Andric                                  const std::string &OldFile,
458*0b57cec5SDimitry Andric                                  const std::string &NewFile) {
459*0b57cec5SDimitry Andric   if (FeaturesDir.empty()) return;
460*0b57cec5SDimitry Andric   RenameFile(DirPlusFile(FeaturesDir, OldFile),
461*0b57cec5SDimitry Andric              DirPlusFile(FeaturesDir, NewFile));
462*0b57cec5SDimitry Andric }
463*0b57cec5SDimitry Andric 
464*0b57cec5SDimitry Andric bool Fuzzer::RunOne(const uint8_t *Data, size_t Size, bool MayDeleteFile,
465*0b57cec5SDimitry Andric                     InputInfo *II, bool *FoundUniqFeatures) {
466*0b57cec5SDimitry Andric   if (!Size)
467*0b57cec5SDimitry Andric     return false;
468*0b57cec5SDimitry Andric 
469*0b57cec5SDimitry Andric   ExecuteCallback(Data, Size);
470*0b57cec5SDimitry Andric 
471*0b57cec5SDimitry Andric   UniqFeatureSetTmp.clear();
472*0b57cec5SDimitry Andric   size_t FoundUniqFeaturesOfII = 0;
473*0b57cec5SDimitry Andric   size_t NumUpdatesBefore = Corpus.NumFeatureUpdates();
474*0b57cec5SDimitry Andric   TPC.CollectFeatures([&](size_t Feature) {
475*0b57cec5SDimitry Andric     if (Corpus.AddFeature(Feature, Size, Options.Shrink))
476*0b57cec5SDimitry Andric       UniqFeatureSetTmp.push_back(Feature);
477*0b57cec5SDimitry Andric     if (Options.ReduceInputs && II)
478*0b57cec5SDimitry Andric       if (std::binary_search(II->UniqFeatureSet.begin(),
479*0b57cec5SDimitry Andric                              II->UniqFeatureSet.end(), Feature))
480*0b57cec5SDimitry Andric         FoundUniqFeaturesOfII++;
481*0b57cec5SDimitry Andric   });
482*0b57cec5SDimitry Andric   if (FoundUniqFeatures)
483*0b57cec5SDimitry Andric     *FoundUniqFeatures = FoundUniqFeaturesOfII;
484*0b57cec5SDimitry Andric   PrintPulseAndReportSlowInput(Data, Size);
485*0b57cec5SDimitry Andric   size_t NumNewFeatures = Corpus.NumFeatureUpdates() - NumUpdatesBefore;
486*0b57cec5SDimitry Andric   if (NumNewFeatures) {
487*0b57cec5SDimitry Andric     TPC.UpdateObservedPCs();
488*0b57cec5SDimitry Andric     auto NewII = Corpus.AddToCorpus({Data, Data + Size}, NumNewFeatures,
489*0b57cec5SDimitry Andric                                     MayDeleteFile, TPC.ObservedFocusFunction(),
490*0b57cec5SDimitry Andric                                     UniqFeatureSetTmp, DFT, II);
491*0b57cec5SDimitry Andric     WriteFeatureSetToFile(Options.FeaturesDir, Sha1ToString(NewII->Sha1),
492*0b57cec5SDimitry Andric                           NewII->UniqFeatureSet);
493*0b57cec5SDimitry Andric     return true;
494*0b57cec5SDimitry Andric   }
495*0b57cec5SDimitry Andric   if (II && FoundUniqFeaturesOfII &&
496*0b57cec5SDimitry Andric       II->DataFlowTraceForFocusFunction.empty() &&
497*0b57cec5SDimitry Andric       FoundUniqFeaturesOfII == II->UniqFeatureSet.size() &&
498*0b57cec5SDimitry Andric       II->U.size() > Size) {
499*0b57cec5SDimitry Andric     auto OldFeaturesFile = Sha1ToString(II->Sha1);
500*0b57cec5SDimitry Andric     Corpus.Replace(II, {Data, Data + Size});
501*0b57cec5SDimitry Andric     RenameFeatureSetFile(Options.FeaturesDir, OldFeaturesFile,
502*0b57cec5SDimitry Andric                          Sha1ToString(II->Sha1));
503*0b57cec5SDimitry Andric     return true;
504*0b57cec5SDimitry Andric   }
505*0b57cec5SDimitry Andric   return false;
506*0b57cec5SDimitry Andric }
507*0b57cec5SDimitry Andric 
508*0b57cec5SDimitry Andric size_t Fuzzer::GetCurrentUnitInFuzzingThead(const uint8_t **Data) const {
509*0b57cec5SDimitry Andric   assert(InFuzzingThread());
510*0b57cec5SDimitry Andric   *Data = CurrentUnitData;
511*0b57cec5SDimitry Andric   return CurrentUnitSize;
512*0b57cec5SDimitry Andric }
513*0b57cec5SDimitry Andric 
514*0b57cec5SDimitry Andric void Fuzzer::CrashOnOverwrittenData() {
515*0b57cec5SDimitry Andric   Printf("==%d== ERROR: libFuzzer: fuzz target overwrites it's const input\n",
516*0b57cec5SDimitry Andric          GetPid());
517*0b57cec5SDimitry Andric   DumpCurrentUnit("crash-");
518*0b57cec5SDimitry Andric   Printf("SUMMARY: libFuzzer: out-of-memory\n");
519*0b57cec5SDimitry Andric   _Exit(Options.ErrorExitCode); // Stop right now.
520*0b57cec5SDimitry Andric }
521*0b57cec5SDimitry Andric 
522*0b57cec5SDimitry Andric // Compare two arrays, but not all bytes if the arrays are large.
523*0b57cec5SDimitry Andric static bool LooseMemeq(const uint8_t *A, const uint8_t *B, size_t Size) {
524*0b57cec5SDimitry Andric   const size_t Limit = 64;
525*0b57cec5SDimitry Andric   if (Size <= 64)
526*0b57cec5SDimitry Andric     return !memcmp(A, B, Size);
527*0b57cec5SDimitry Andric   // Compare first and last Limit/2 bytes.
528*0b57cec5SDimitry Andric   return !memcmp(A, B, Limit / 2) &&
529*0b57cec5SDimitry Andric          !memcmp(A + Size - Limit / 2, B + Size - Limit / 2, Limit / 2);
530*0b57cec5SDimitry Andric }
531*0b57cec5SDimitry Andric 
532*0b57cec5SDimitry Andric void Fuzzer::ExecuteCallback(const uint8_t *Data, size_t Size) {
533*0b57cec5SDimitry Andric   TPC.RecordInitialStack();
534*0b57cec5SDimitry Andric   TotalNumberOfRuns++;
535*0b57cec5SDimitry Andric   assert(InFuzzingThread());
536*0b57cec5SDimitry Andric   // We copy the contents of Unit into a separate heap buffer
537*0b57cec5SDimitry Andric   // so that we reliably find buffer overflows in it.
538*0b57cec5SDimitry Andric   uint8_t *DataCopy = new uint8_t[Size];
539*0b57cec5SDimitry Andric   memcpy(DataCopy, Data, Size);
540*0b57cec5SDimitry Andric   if (EF->__msan_unpoison)
541*0b57cec5SDimitry Andric     EF->__msan_unpoison(DataCopy, Size);
542*0b57cec5SDimitry Andric   if (EF->__msan_unpoison_param)
543*0b57cec5SDimitry Andric     EF->__msan_unpoison_param(2);
544*0b57cec5SDimitry Andric   if (CurrentUnitData && CurrentUnitData != Data)
545*0b57cec5SDimitry Andric     memcpy(CurrentUnitData, Data, Size);
546*0b57cec5SDimitry Andric   CurrentUnitSize = Size;
547*0b57cec5SDimitry Andric   {
548*0b57cec5SDimitry Andric     ScopedEnableMsanInterceptorChecks S;
549*0b57cec5SDimitry Andric     AllocTracer.Start(Options.TraceMalloc);
550*0b57cec5SDimitry Andric     UnitStartTime = system_clock::now();
551*0b57cec5SDimitry Andric     TPC.ResetMaps();
552*0b57cec5SDimitry Andric     RunningUserCallback = true;
553*0b57cec5SDimitry Andric     int Res = CB(DataCopy, Size);
554*0b57cec5SDimitry Andric     RunningUserCallback = false;
555*0b57cec5SDimitry Andric     UnitStopTime = system_clock::now();
556*0b57cec5SDimitry Andric     (void)Res;
557*0b57cec5SDimitry Andric     assert(Res == 0);
558*0b57cec5SDimitry Andric     HasMoreMallocsThanFrees = AllocTracer.Stop();
559*0b57cec5SDimitry Andric   }
560*0b57cec5SDimitry Andric   if (!LooseMemeq(DataCopy, Data, Size))
561*0b57cec5SDimitry Andric     CrashOnOverwrittenData();
562*0b57cec5SDimitry Andric   CurrentUnitSize = 0;
563*0b57cec5SDimitry Andric   delete[] DataCopy;
564*0b57cec5SDimitry Andric }
565*0b57cec5SDimitry Andric 
566*0b57cec5SDimitry Andric std::string Fuzzer::WriteToOutputCorpus(const Unit &U) {
567*0b57cec5SDimitry Andric   if (Options.OnlyASCII)
568*0b57cec5SDimitry Andric     assert(IsASCII(U));
569*0b57cec5SDimitry Andric   if (Options.OutputCorpus.empty())
570*0b57cec5SDimitry Andric     return "";
571*0b57cec5SDimitry Andric   std::string Path = DirPlusFile(Options.OutputCorpus, Hash(U));
572*0b57cec5SDimitry Andric   WriteToFile(U, Path);
573*0b57cec5SDimitry Andric   if (Options.Verbosity >= 2)
574*0b57cec5SDimitry Andric     Printf("Written %zd bytes to %s\n", U.size(), Path.c_str());
575*0b57cec5SDimitry Andric   return Path;
576*0b57cec5SDimitry Andric }
577*0b57cec5SDimitry Andric 
578*0b57cec5SDimitry Andric void Fuzzer::WriteUnitToFileWithPrefix(const Unit &U, const char *Prefix) {
579*0b57cec5SDimitry Andric   if (!Options.SaveArtifacts)
580*0b57cec5SDimitry Andric     return;
581*0b57cec5SDimitry Andric   std::string Path = Options.ArtifactPrefix + Prefix + Hash(U);
582*0b57cec5SDimitry Andric   if (!Options.ExactArtifactPath.empty())
583*0b57cec5SDimitry Andric     Path = Options.ExactArtifactPath; // Overrides ArtifactPrefix.
584*0b57cec5SDimitry Andric   WriteToFile(U, Path);
585*0b57cec5SDimitry Andric   Printf("artifact_prefix='%s'; Test unit written to %s\n",
586*0b57cec5SDimitry Andric          Options.ArtifactPrefix.c_str(), Path.c_str());
587*0b57cec5SDimitry Andric   if (U.size() <= kMaxUnitSizeToPrint)
588*0b57cec5SDimitry Andric     Printf("Base64: %s\n", Base64(U).c_str());
589*0b57cec5SDimitry Andric }
590*0b57cec5SDimitry Andric 
591*0b57cec5SDimitry Andric void Fuzzer::PrintStatusForNewUnit(const Unit &U, const char *Text) {
592*0b57cec5SDimitry Andric   if (!Options.PrintNEW)
593*0b57cec5SDimitry Andric     return;
594*0b57cec5SDimitry Andric   PrintStats(Text, "");
595*0b57cec5SDimitry Andric   if (Options.Verbosity) {
596*0b57cec5SDimitry Andric     Printf(" L: %zd/%zd ", U.size(), Corpus.MaxInputSize());
597*0b57cec5SDimitry Andric     MD.PrintMutationSequence();
598*0b57cec5SDimitry Andric     Printf("\n");
599*0b57cec5SDimitry Andric   }
600*0b57cec5SDimitry Andric }
601*0b57cec5SDimitry Andric 
602*0b57cec5SDimitry Andric void Fuzzer::ReportNewCoverage(InputInfo *II, const Unit &U) {
603*0b57cec5SDimitry Andric   II->NumSuccessfullMutations++;
604*0b57cec5SDimitry Andric   MD.RecordSuccessfulMutationSequence();
605*0b57cec5SDimitry Andric   PrintStatusForNewUnit(U, II->Reduced ? "REDUCE" : "NEW   ");
606*0b57cec5SDimitry Andric   WriteToOutputCorpus(U);
607*0b57cec5SDimitry Andric   NumberOfNewUnitsAdded++;
608*0b57cec5SDimitry Andric   CheckExitOnSrcPosOrItem(); // Check only after the unit is saved to corpus.
609*0b57cec5SDimitry Andric   LastCorpusUpdateRun = TotalNumberOfRuns;
610*0b57cec5SDimitry Andric }
611*0b57cec5SDimitry Andric 
612*0b57cec5SDimitry Andric // Tries detecting a memory leak on the particular input that we have just
613*0b57cec5SDimitry Andric // executed before calling this function.
614*0b57cec5SDimitry Andric void Fuzzer::TryDetectingAMemoryLeak(const uint8_t *Data, size_t Size,
615*0b57cec5SDimitry Andric                                      bool DuringInitialCorpusExecution) {
616*0b57cec5SDimitry Andric   if (!HasMoreMallocsThanFrees)
617*0b57cec5SDimitry Andric     return; // mallocs==frees, a leak is unlikely.
618*0b57cec5SDimitry Andric   if (!Options.DetectLeaks)
619*0b57cec5SDimitry Andric     return;
620*0b57cec5SDimitry Andric   if (!DuringInitialCorpusExecution &&
621*0b57cec5SDimitry Andric       TotalNumberOfRuns >= Options.MaxNumberOfRuns)
622*0b57cec5SDimitry Andric     return;
623*0b57cec5SDimitry Andric   if (!&(EF->__lsan_enable) || !&(EF->__lsan_disable) ||
624*0b57cec5SDimitry Andric       !(EF->__lsan_do_recoverable_leak_check))
625*0b57cec5SDimitry Andric     return; // No lsan.
626*0b57cec5SDimitry Andric   // Run the target once again, but with lsan disabled so that if there is
627*0b57cec5SDimitry Andric   // a real leak we do not report it twice.
628*0b57cec5SDimitry Andric   EF->__lsan_disable();
629*0b57cec5SDimitry Andric   ExecuteCallback(Data, Size);
630*0b57cec5SDimitry Andric   EF->__lsan_enable();
631*0b57cec5SDimitry Andric   if (!HasMoreMallocsThanFrees)
632*0b57cec5SDimitry Andric     return; // a leak is unlikely.
633*0b57cec5SDimitry Andric   if (NumberOfLeakDetectionAttempts++ > 1000) {
634*0b57cec5SDimitry Andric     Options.DetectLeaks = false;
635*0b57cec5SDimitry Andric     Printf("INFO: libFuzzer disabled leak detection after every mutation.\n"
636*0b57cec5SDimitry Andric            "      Most likely the target function accumulates allocated\n"
637*0b57cec5SDimitry Andric            "      memory in a global state w/o actually leaking it.\n"
638*0b57cec5SDimitry Andric            "      You may try running this binary with -trace_malloc=[12]"
639*0b57cec5SDimitry Andric            "      to get a trace of mallocs and frees.\n"
640*0b57cec5SDimitry Andric            "      If LeakSanitizer is enabled in this process it will still\n"
641*0b57cec5SDimitry Andric            "      run on the process shutdown.\n");
642*0b57cec5SDimitry Andric     return;
643*0b57cec5SDimitry Andric   }
644*0b57cec5SDimitry Andric   // Now perform the actual lsan pass. This is expensive and we must ensure
645*0b57cec5SDimitry Andric   // we don't call it too often.
646*0b57cec5SDimitry Andric   if (EF->__lsan_do_recoverable_leak_check()) { // Leak is found, report it.
647*0b57cec5SDimitry Andric     if (DuringInitialCorpusExecution)
648*0b57cec5SDimitry Andric       Printf("\nINFO: a leak has been found in the initial corpus.\n\n");
649*0b57cec5SDimitry Andric     Printf("INFO: to ignore leaks on libFuzzer side use -detect_leaks=0.\n\n");
650*0b57cec5SDimitry Andric     CurrentUnitSize = Size;
651*0b57cec5SDimitry Andric     DumpCurrentUnit("leak-");
652*0b57cec5SDimitry Andric     PrintFinalStats();
653*0b57cec5SDimitry Andric     _Exit(Options.ErrorExitCode); // not exit() to disable lsan further on.
654*0b57cec5SDimitry Andric   }
655*0b57cec5SDimitry Andric }
656*0b57cec5SDimitry Andric 
657*0b57cec5SDimitry Andric void Fuzzer::MutateAndTestOne() {
658*0b57cec5SDimitry Andric   MD.StartMutationSequence();
659*0b57cec5SDimitry Andric 
660*0b57cec5SDimitry Andric   auto &II = Corpus.ChooseUnitToMutate(MD.GetRand());
661*0b57cec5SDimitry Andric   if (Options.DoCrossOver)
662*0b57cec5SDimitry Andric     MD.SetCrossOverWith(&Corpus.ChooseUnitToMutate(MD.GetRand()).U);
663*0b57cec5SDimitry Andric   const auto &U = II.U;
664*0b57cec5SDimitry Andric   memcpy(BaseSha1, II.Sha1, sizeof(BaseSha1));
665*0b57cec5SDimitry Andric   assert(CurrentUnitData);
666*0b57cec5SDimitry Andric   size_t Size = U.size();
667*0b57cec5SDimitry Andric   assert(Size <= MaxInputLen && "Oversized Unit");
668*0b57cec5SDimitry Andric   memcpy(CurrentUnitData, U.data(), Size);
669*0b57cec5SDimitry Andric 
670*0b57cec5SDimitry Andric   assert(MaxMutationLen > 0);
671*0b57cec5SDimitry Andric 
672*0b57cec5SDimitry Andric   size_t CurrentMaxMutationLen =
673*0b57cec5SDimitry Andric       Min(MaxMutationLen, Max(U.size(), TmpMaxMutationLen));
674*0b57cec5SDimitry Andric   assert(CurrentMaxMutationLen > 0);
675*0b57cec5SDimitry Andric 
676*0b57cec5SDimitry Andric   for (int i = 0; i < Options.MutateDepth; i++) {
677*0b57cec5SDimitry Andric     if (TotalNumberOfRuns >= Options.MaxNumberOfRuns)
678*0b57cec5SDimitry Andric       break;
679*0b57cec5SDimitry Andric     MaybeExitGracefully();
680*0b57cec5SDimitry Andric     size_t NewSize = 0;
681*0b57cec5SDimitry Andric     if (II.HasFocusFunction && !II.DataFlowTraceForFocusFunction.empty() &&
682*0b57cec5SDimitry Andric         Size <= CurrentMaxMutationLen)
683*0b57cec5SDimitry Andric       NewSize = MD.MutateWithMask(CurrentUnitData, Size, Size,
684*0b57cec5SDimitry Andric                                   II.DataFlowTraceForFocusFunction);
685*0b57cec5SDimitry Andric 
686*0b57cec5SDimitry Andric     // If MutateWithMask either failed or wasn't called, call default Mutate.
687*0b57cec5SDimitry Andric     if (!NewSize)
688*0b57cec5SDimitry Andric       NewSize = MD.Mutate(CurrentUnitData, Size, CurrentMaxMutationLen);
689*0b57cec5SDimitry Andric     assert(NewSize > 0 && "Mutator returned empty unit");
690*0b57cec5SDimitry Andric     assert(NewSize <= CurrentMaxMutationLen && "Mutator return oversized unit");
691*0b57cec5SDimitry Andric     Size = NewSize;
692*0b57cec5SDimitry Andric     II.NumExecutedMutations++;
693*0b57cec5SDimitry Andric 
694*0b57cec5SDimitry Andric     bool FoundUniqFeatures = false;
695*0b57cec5SDimitry Andric     bool NewCov = RunOne(CurrentUnitData, Size, /*MayDeleteFile=*/true, &II,
696*0b57cec5SDimitry Andric                          &FoundUniqFeatures);
697*0b57cec5SDimitry Andric     TryDetectingAMemoryLeak(CurrentUnitData, Size,
698*0b57cec5SDimitry Andric                             /*DuringInitialCorpusExecution*/ false);
699*0b57cec5SDimitry Andric     if (NewCov) {
700*0b57cec5SDimitry Andric       ReportNewCoverage(&II, {CurrentUnitData, CurrentUnitData + Size});
701*0b57cec5SDimitry Andric       break;  // We will mutate this input more in the next rounds.
702*0b57cec5SDimitry Andric     }
703*0b57cec5SDimitry Andric     if (Options.ReduceDepth && !FoundUniqFeatures)
704*0b57cec5SDimitry Andric       break;
705*0b57cec5SDimitry Andric   }
706*0b57cec5SDimitry Andric }
707*0b57cec5SDimitry Andric 
708*0b57cec5SDimitry Andric void Fuzzer::PurgeAllocator() {
709*0b57cec5SDimitry Andric   if (Options.PurgeAllocatorIntervalSec < 0 || !EF->__sanitizer_purge_allocator)
710*0b57cec5SDimitry Andric     return;
711*0b57cec5SDimitry Andric   if (duration_cast<seconds>(system_clock::now() -
712*0b57cec5SDimitry Andric                              LastAllocatorPurgeAttemptTime)
713*0b57cec5SDimitry Andric           .count() < Options.PurgeAllocatorIntervalSec)
714*0b57cec5SDimitry Andric     return;
715*0b57cec5SDimitry Andric 
716*0b57cec5SDimitry Andric   if (Options.RssLimitMb <= 0 ||
717*0b57cec5SDimitry Andric       GetPeakRSSMb() > static_cast<size_t>(Options.RssLimitMb) / 2)
718*0b57cec5SDimitry Andric     EF->__sanitizer_purge_allocator();
719*0b57cec5SDimitry Andric 
720*0b57cec5SDimitry Andric   LastAllocatorPurgeAttemptTime = system_clock::now();
721*0b57cec5SDimitry Andric }
722*0b57cec5SDimitry Andric 
723*0b57cec5SDimitry Andric void Fuzzer::ReadAndExecuteSeedCorpora(Vector<SizedFile> &CorporaFiles) {
724*0b57cec5SDimitry Andric   const size_t kMaxSaneLen = 1 << 20;
725*0b57cec5SDimitry Andric   const size_t kMinDefaultLen = 4096;
726*0b57cec5SDimitry Andric   size_t MaxSize = 0;
727*0b57cec5SDimitry Andric   size_t MinSize = -1;
728*0b57cec5SDimitry Andric   size_t TotalSize = 0;
729*0b57cec5SDimitry Andric   for (auto &File : CorporaFiles) {
730*0b57cec5SDimitry Andric     MaxSize = Max(File.Size, MaxSize);
731*0b57cec5SDimitry Andric     MinSize = Min(File.Size, MinSize);
732*0b57cec5SDimitry Andric     TotalSize += File.Size;
733*0b57cec5SDimitry Andric   }
734*0b57cec5SDimitry Andric   if (Options.MaxLen == 0)
735*0b57cec5SDimitry Andric     SetMaxInputLen(std::min(std::max(kMinDefaultLen, MaxSize), kMaxSaneLen));
736*0b57cec5SDimitry Andric   assert(MaxInputLen > 0);
737*0b57cec5SDimitry Andric 
738*0b57cec5SDimitry Andric   // Test the callback with empty input and never try it again.
739*0b57cec5SDimitry Andric   uint8_t dummy = 0;
740*0b57cec5SDimitry Andric   ExecuteCallback(&dummy, 0);
741*0b57cec5SDimitry Andric 
742*0b57cec5SDimitry Andric   // Protect lazy counters here, after the once-init code has been executed.
743*0b57cec5SDimitry Andric   if (Options.LazyCounters)
744*0b57cec5SDimitry Andric     TPC.ProtectLazyCounters();
745*0b57cec5SDimitry Andric 
746*0b57cec5SDimitry Andric   if (CorporaFiles.empty()) {
747*0b57cec5SDimitry Andric     Printf("INFO: A corpus is not provided, starting from an empty corpus\n");
748*0b57cec5SDimitry Andric     Unit U({'\n'}); // Valid ASCII input.
749*0b57cec5SDimitry Andric     RunOne(U.data(), U.size());
750*0b57cec5SDimitry Andric   } else {
751*0b57cec5SDimitry Andric     Printf("INFO: seed corpus: files: %zd min: %zdb max: %zdb total: %zdb"
752*0b57cec5SDimitry Andric            " rss: %zdMb\n",
753*0b57cec5SDimitry Andric            CorporaFiles.size(), MinSize, MaxSize, TotalSize, GetPeakRSSMb());
754*0b57cec5SDimitry Andric     if (Options.ShuffleAtStartUp)
755*0b57cec5SDimitry Andric       std::shuffle(CorporaFiles.begin(), CorporaFiles.end(), MD.GetRand());
756*0b57cec5SDimitry Andric 
757*0b57cec5SDimitry Andric     if (Options.PreferSmall) {
758*0b57cec5SDimitry Andric       std::stable_sort(CorporaFiles.begin(), CorporaFiles.end());
759*0b57cec5SDimitry Andric       assert(CorporaFiles.front().Size <= CorporaFiles.back().Size);
760*0b57cec5SDimitry Andric     }
761*0b57cec5SDimitry Andric 
762*0b57cec5SDimitry Andric     // Load and execute inputs one by one.
763*0b57cec5SDimitry Andric     for (auto &SF : CorporaFiles) {
764*0b57cec5SDimitry Andric       auto U = FileToVector(SF.File, MaxInputLen, /*ExitOnError=*/false);
765*0b57cec5SDimitry Andric       assert(U.size() <= MaxInputLen);
766*0b57cec5SDimitry Andric       RunOne(U.data(), U.size());
767*0b57cec5SDimitry Andric       CheckExitOnSrcPosOrItem();
768*0b57cec5SDimitry Andric       TryDetectingAMemoryLeak(U.data(), U.size(),
769*0b57cec5SDimitry Andric                               /*DuringInitialCorpusExecution*/ true);
770*0b57cec5SDimitry Andric     }
771*0b57cec5SDimitry Andric   }
772*0b57cec5SDimitry Andric 
773*0b57cec5SDimitry Andric   PrintStats("INITED");
774*0b57cec5SDimitry Andric   if (!Options.FocusFunction.empty())
775*0b57cec5SDimitry Andric     Printf("INFO: %zd/%zd inputs touch the focus function\n",
776*0b57cec5SDimitry Andric            Corpus.NumInputsThatTouchFocusFunction(), Corpus.size());
777*0b57cec5SDimitry Andric   if (!Options.DataFlowTrace.empty())
778*0b57cec5SDimitry Andric     Printf("INFO: %zd/%zd inputs have the Data Flow Trace\n",
779*0b57cec5SDimitry Andric            Corpus.NumInputsWithDataFlowTrace(), Corpus.size());
780*0b57cec5SDimitry Andric 
781*0b57cec5SDimitry Andric   if (Corpus.empty() && Options.MaxNumberOfRuns) {
782*0b57cec5SDimitry Andric     Printf("ERROR: no interesting inputs were found. "
783*0b57cec5SDimitry Andric            "Is the code instrumented for coverage? Exiting.\n");
784*0b57cec5SDimitry Andric     exit(1);
785*0b57cec5SDimitry Andric   }
786*0b57cec5SDimitry Andric }
787*0b57cec5SDimitry Andric 
788*0b57cec5SDimitry Andric void Fuzzer::Loop(Vector<SizedFile> &CorporaFiles) {
789*0b57cec5SDimitry Andric   auto FocusFunctionOrAuto = Options.FocusFunction;
790*0b57cec5SDimitry Andric   DFT.Init(Options.DataFlowTrace, &FocusFunctionOrAuto, CorporaFiles,
791*0b57cec5SDimitry Andric            MD.GetRand());
792*0b57cec5SDimitry Andric   TPC.SetFocusFunction(FocusFunctionOrAuto);
793*0b57cec5SDimitry Andric   ReadAndExecuteSeedCorpora(CorporaFiles);
794*0b57cec5SDimitry Andric   DFT.Clear();  // No need for DFT any more.
795*0b57cec5SDimitry Andric   TPC.SetPrintNewPCs(Options.PrintNewCovPcs);
796*0b57cec5SDimitry Andric   TPC.SetPrintNewFuncs(Options.PrintNewCovFuncs);
797*0b57cec5SDimitry Andric   system_clock::time_point LastCorpusReload = system_clock::now();
798*0b57cec5SDimitry Andric 
799*0b57cec5SDimitry Andric   TmpMaxMutationLen =
800*0b57cec5SDimitry Andric       Min(MaxMutationLen, Max(size_t(4), Corpus.MaxInputSize()));
801*0b57cec5SDimitry Andric 
802*0b57cec5SDimitry Andric   while (true) {
803*0b57cec5SDimitry Andric     auto Now = system_clock::now();
804*0b57cec5SDimitry Andric     if (!Options.StopFile.empty() &&
805*0b57cec5SDimitry Andric         !FileToVector(Options.StopFile, 1, false).empty())
806*0b57cec5SDimitry Andric       break;
807*0b57cec5SDimitry Andric     if (duration_cast<seconds>(Now - LastCorpusReload).count() >=
808*0b57cec5SDimitry Andric         Options.ReloadIntervalSec) {
809*0b57cec5SDimitry Andric       RereadOutputCorpus(MaxInputLen);
810*0b57cec5SDimitry Andric       LastCorpusReload = system_clock::now();
811*0b57cec5SDimitry Andric     }
812*0b57cec5SDimitry Andric     if (TotalNumberOfRuns >= Options.MaxNumberOfRuns)
813*0b57cec5SDimitry Andric       break;
814*0b57cec5SDimitry Andric     if (TimedOut())
815*0b57cec5SDimitry Andric       break;
816*0b57cec5SDimitry Andric 
817*0b57cec5SDimitry Andric     // Update TmpMaxMutationLen
818*0b57cec5SDimitry Andric     if (Options.LenControl) {
819*0b57cec5SDimitry Andric       if (TmpMaxMutationLen < MaxMutationLen &&
820*0b57cec5SDimitry Andric           TotalNumberOfRuns - LastCorpusUpdateRun >
821*0b57cec5SDimitry Andric               Options.LenControl * Log(TmpMaxMutationLen)) {
822*0b57cec5SDimitry Andric         TmpMaxMutationLen =
823*0b57cec5SDimitry Andric             Min(MaxMutationLen, TmpMaxMutationLen + Log(TmpMaxMutationLen));
824*0b57cec5SDimitry Andric         LastCorpusUpdateRun = TotalNumberOfRuns;
825*0b57cec5SDimitry Andric       }
826*0b57cec5SDimitry Andric     } else {
827*0b57cec5SDimitry Andric       TmpMaxMutationLen = MaxMutationLen;
828*0b57cec5SDimitry Andric     }
829*0b57cec5SDimitry Andric 
830*0b57cec5SDimitry Andric     // Perform several mutations and runs.
831*0b57cec5SDimitry Andric     MutateAndTestOne();
832*0b57cec5SDimitry Andric 
833*0b57cec5SDimitry Andric     PurgeAllocator();
834*0b57cec5SDimitry Andric   }
835*0b57cec5SDimitry Andric 
836*0b57cec5SDimitry Andric   PrintStats("DONE  ", "\n");
837*0b57cec5SDimitry Andric   MD.PrintRecommendedDictionary();
838*0b57cec5SDimitry Andric }
839*0b57cec5SDimitry Andric 
840*0b57cec5SDimitry Andric void Fuzzer::MinimizeCrashLoop(const Unit &U) {
841*0b57cec5SDimitry Andric   if (U.size() <= 1)
842*0b57cec5SDimitry Andric     return;
843*0b57cec5SDimitry Andric   while (!TimedOut() && TotalNumberOfRuns < Options.MaxNumberOfRuns) {
844*0b57cec5SDimitry Andric     MD.StartMutationSequence();
845*0b57cec5SDimitry Andric     memcpy(CurrentUnitData, U.data(), U.size());
846*0b57cec5SDimitry Andric     for (int i = 0; i < Options.MutateDepth; i++) {
847*0b57cec5SDimitry Andric       size_t NewSize = MD.Mutate(CurrentUnitData, U.size(), MaxMutationLen);
848*0b57cec5SDimitry Andric       assert(NewSize > 0 && NewSize <= MaxMutationLen);
849*0b57cec5SDimitry Andric       ExecuteCallback(CurrentUnitData, NewSize);
850*0b57cec5SDimitry Andric       PrintPulseAndReportSlowInput(CurrentUnitData, NewSize);
851*0b57cec5SDimitry Andric       TryDetectingAMemoryLeak(CurrentUnitData, NewSize,
852*0b57cec5SDimitry Andric                               /*DuringInitialCorpusExecution*/ false);
853*0b57cec5SDimitry Andric     }
854*0b57cec5SDimitry Andric   }
855*0b57cec5SDimitry Andric }
856*0b57cec5SDimitry Andric 
857*0b57cec5SDimitry Andric } // namespace fuzzer
858*0b57cec5SDimitry Andric 
859*0b57cec5SDimitry Andric extern "C" {
860*0b57cec5SDimitry Andric 
861*0b57cec5SDimitry Andric ATTRIBUTE_INTERFACE size_t
862*0b57cec5SDimitry Andric LLVMFuzzerMutate(uint8_t *Data, size_t Size, size_t MaxSize) {
863*0b57cec5SDimitry Andric   assert(fuzzer::F);
864*0b57cec5SDimitry Andric   return fuzzer::F->GetMD().DefaultMutate(Data, Size, MaxSize);
865*0b57cec5SDimitry Andric }
866*0b57cec5SDimitry Andric 
867*0b57cec5SDimitry Andric } // extern "C"
868