1 //===- FuzzerLoop.cpp - Fuzzer's main loop --------------------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 // Fuzzer's main loop.
10 //===----------------------------------------------------------------------===//
11 
12 #include "FuzzerCorpus.h"
13 #include "FuzzerIO.h"
14 #include "FuzzerInternal.h"
15 #include "FuzzerMutate.h"
16 #include "FuzzerRandom.h"
17 #include "FuzzerShmem.h"
18 #include "FuzzerTracePC.h"
19 #include <algorithm>
20 #include <cstring>
21 #include <memory>
22 #include <set>
23 
24 #if defined(__has_include)
25 #if __has_include(<sanitizer / lsan_interface.h>)
26 #include <sanitizer/lsan_interface.h>
27 #endif
28 #endif
29 
30 #define NO_SANITIZE_MEMORY
31 #if defined(__has_feature)
32 #if __has_feature(memory_sanitizer)
33 #undef NO_SANITIZE_MEMORY
34 #define NO_SANITIZE_MEMORY __attribute__((no_sanitize_memory))
35 #endif
36 #endif
37 
38 namespace fuzzer {
39 static const size_t kMaxUnitSizeToPrint = 256;
40 
41 thread_local bool Fuzzer::IsMyThread;
42 
43 SharedMemoryRegion SMR;
44 
45 // Only one Fuzzer per process.
46 static Fuzzer *F;
47 
48 // Leak detection is expensive, so we first check if there were more mallocs
49 // than frees (using the sanitizer malloc hooks) and only then try to call lsan.
50 struct MallocFreeTracer {
51   void Start(int TraceLevel) {
52     this->TraceLevel = TraceLevel;
53     if (TraceLevel)
54       Printf("MallocFreeTracer: START\n");
55     Mallocs = 0;
56     Frees = 0;
57   }
58   // Returns true if there were more mallocs than frees.
59   bool Stop() {
60     if (TraceLevel)
61       Printf("MallocFreeTracer: STOP %zd %zd (%s)\n", Mallocs.load(),
62              Frees.load(), Mallocs == Frees ? "same" : "DIFFERENT");
63     bool Result = Mallocs > Frees;
64     Mallocs = 0;
65     Frees = 0;
66     TraceLevel = 0;
67     return Result;
68   }
69   std::atomic<size_t> Mallocs;
70   std::atomic<size_t> Frees;
71   int TraceLevel = 0;
72 };
73 
74 static MallocFreeTracer AllocTracer;
75 
76 ATTRIBUTE_NO_SANITIZE_MEMORY
77 void MallocHook(const volatile void *ptr, size_t size) {
78   size_t N = AllocTracer.Mallocs++;
79   F->HandleMalloc(size);
80   if (int TraceLevel = AllocTracer.TraceLevel) {
81     Printf("MALLOC[%zd] %p %zd\n", N, ptr, size);
82     if (TraceLevel >= 2 && EF)
83       EF->__sanitizer_print_stack_trace();
84   }
85 }
86 
87 ATTRIBUTE_NO_SANITIZE_MEMORY
88 void FreeHook(const volatile void *ptr) {
89   size_t N = AllocTracer.Frees++;
90   if (int TraceLevel = AllocTracer.TraceLevel) {
91     Printf("FREE[%zd]   %p\n", N, ptr);
92     if (TraceLevel >= 2 && EF)
93       EF->__sanitizer_print_stack_trace();
94   }
95 }
96 
97 // Crash on a single malloc that exceeds the rss limit.
98 void Fuzzer::HandleMalloc(size_t Size) {
99   if (!Options.RssLimitMb || (Size >> 20) < (size_t)Options.RssLimitMb)
100     return;
101   Printf("==%d== ERROR: libFuzzer: out-of-memory (malloc(%zd))\n", GetPid(),
102          Size);
103   Printf("   To change the out-of-memory limit use -rss_limit_mb=<N>\n\n");
104   if (EF->__sanitizer_print_stack_trace)
105     EF->__sanitizer_print_stack_trace();
106   DumpCurrentUnit("oom-");
107   Printf("SUMMARY: libFuzzer: out-of-memory\n");
108   PrintFinalStats();
109   _Exit(Options.ErrorExitCode); // Stop right now.
110 }
111 
112 Fuzzer::Fuzzer(UserCallback CB, InputCorpus &Corpus, MutationDispatcher &MD,
113                FuzzingOptions Options)
114     : CB(CB), Corpus(Corpus), MD(MD), Options(Options) {
115   if (EF->__sanitizer_set_death_callback)
116     EF->__sanitizer_set_death_callback(StaticDeathCallback);
117   assert(!F);
118   F = this;
119   TPC.ResetMaps();
120   IsMyThread = true;
121   if (Options.DetectLeaks && EF->__sanitizer_install_malloc_and_free_hooks)
122     EF->__sanitizer_install_malloc_and_free_hooks(MallocHook, FreeHook);
123   TPC.SetUseCounters(Options.UseCounters);
124   TPC.SetUseValueProfile(Options.UseValueProfile);
125 
126   if (Options.Verbosity)
127     TPC.PrintModuleInfo();
128   if (!Options.OutputCorpus.empty() && Options.ReloadIntervalSec)
129     EpochOfLastReadOfOutputCorpus = GetEpoch(Options.OutputCorpus);
130   MaxInputLen = MaxMutationLen = Options.MaxLen;
131   TmpMaxMutationLen = Max(size_t(4), Corpus.MaxInputSize());
132   AllocateCurrentUnitData();
133   CurrentUnitSize = 0;
134   memset(BaseSha1, 0, sizeof(BaseSha1));
135 }
136 
137 Fuzzer::~Fuzzer() { }
138 
139 void Fuzzer::AllocateCurrentUnitData() {
140   if (CurrentUnitData || MaxInputLen == 0) return;
141   CurrentUnitData = new uint8_t[MaxInputLen];
142 }
143 
144 void Fuzzer::StaticDeathCallback() {
145   assert(F);
146   F->DeathCallback();
147 }
148 
149 void Fuzzer::DumpCurrentUnit(const char *Prefix) {
150   if (!CurrentUnitData) return;  // Happens when running individual inputs.
151   MD.PrintMutationSequence();
152   Printf("; base unit: %s\n", Sha1ToString(BaseSha1).c_str());
153   size_t UnitSize = CurrentUnitSize;
154   if (UnitSize <= kMaxUnitSizeToPrint) {
155     PrintHexArray(CurrentUnitData, UnitSize, "\n");
156     PrintASCII(CurrentUnitData, UnitSize, "\n");
157   }
158   WriteUnitToFileWithPrefix({CurrentUnitData, CurrentUnitData + UnitSize},
159                             Prefix);
160 }
161 
162 NO_SANITIZE_MEMORY
163 void Fuzzer::DeathCallback() {
164   DumpCurrentUnit("crash-");
165   PrintFinalStats();
166 }
167 
168 void Fuzzer::StaticAlarmCallback() {
169   assert(F);
170   F->AlarmCallback();
171 }
172 
173 void Fuzzer::StaticCrashSignalCallback() {
174   assert(F);
175   F->CrashCallback();
176 }
177 
178 void Fuzzer::StaticExitCallback() {
179   assert(F);
180   F->ExitCallback();
181 }
182 
183 void Fuzzer::StaticInterruptCallback() {
184   assert(F);
185   F->InterruptCallback();
186 }
187 
188 void Fuzzer::StaticFileSizeExceedCallback() {
189   Printf("==%lu== ERROR: libFuzzer: file size exceeded\n", GetPid());
190   exit(1);
191 }
192 
193 void Fuzzer::CrashCallback() {
194   Printf("==%lu== ERROR: libFuzzer: deadly signal\n", GetPid());
195   if (EF->__sanitizer_print_stack_trace)
196     EF->__sanitizer_print_stack_trace();
197   Printf("NOTE: libFuzzer has rudimentary signal handlers.\n"
198          "      Combine libFuzzer with AddressSanitizer or similar for better "
199          "crash reports.\n");
200   Printf("SUMMARY: libFuzzer: deadly signal\n");
201   DumpCurrentUnit("crash-");
202   PrintFinalStats();
203   _Exit(Options.ErrorExitCode);  // Stop right now.
204 }
205 
206 void Fuzzer::ExitCallback() {
207   if (!RunningCB)
208     return; // This exit did not come from the user callback
209   Printf("==%lu== ERROR: libFuzzer: fuzz target exited\n", GetPid());
210   if (EF->__sanitizer_print_stack_trace)
211     EF->__sanitizer_print_stack_trace();
212   Printf("SUMMARY: libFuzzer: fuzz target exited\n");
213   DumpCurrentUnit("crash-");
214   PrintFinalStats();
215   _Exit(Options.ErrorExitCode);
216 }
217 
218 
219 void Fuzzer::InterruptCallback() {
220   Printf("==%lu== libFuzzer: run interrupted; exiting\n", GetPid());
221   PrintFinalStats();
222   _Exit(0);  // Stop right now, don't perform any at-exit actions.
223 }
224 
225 NO_SANITIZE_MEMORY
226 void Fuzzer::AlarmCallback() {
227   assert(Options.UnitTimeoutSec > 0);
228   // In Windows Alarm callback is executed by a different thread.
229 #if !LIBFUZZER_WINDOWS
230   if (!InFuzzingThread()) return;
231 #endif
232   if (!RunningCB)
233     return; // We have not started running units yet.
234   size_t Seconds =
235       duration_cast<seconds>(system_clock::now() - UnitStartTime).count();
236   if (Seconds == 0)
237     return;
238   if (Options.Verbosity >= 2)
239     Printf("AlarmCallback %zd\n", Seconds);
240   if (Seconds >= (size_t)Options.UnitTimeoutSec) {
241     Printf("ALARM: working on the last Unit for %zd seconds\n", Seconds);
242     Printf("       and the timeout value is %d (use -timeout=N to change)\n",
243            Options.UnitTimeoutSec);
244     DumpCurrentUnit("timeout-");
245     Printf("==%lu== ERROR: libFuzzer: timeout after %d seconds\n", GetPid(),
246            Seconds);
247     if (EF->__sanitizer_print_stack_trace)
248       EF->__sanitizer_print_stack_trace();
249     Printf("SUMMARY: libFuzzer: timeout\n");
250     PrintFinalStats();
251     _Exit(Options.TimeoutExitCode); // Stop right now.
252   }
253 }
254 
255 void Fuzzer::RssLimitCallback() {
256   Printf(
257       "==%lu== ERROR: libFuzzer: out-of-memory (used: %zdMb; limit: %zdMb)\n",
258       GetPid(), GetPeakRSSMb(), Options.RssLimitMb);
259   Printf("   To change the out-of-memory limit use -rss_limit_mb=<N>\n\n");
260   if (EF->__sanitizer_print_memory_profile)
261     EF->__sanitizer_print_memory_profile(95, 8);
262   DumpCurrentUnit("oom-");
263   Printf("SUMMARY: libFuzzer: out-of-memory\n");
264   PrintFinalStats();
265   _Exit(Options.ErrorExitCode); // Stop right now.
266 }
267 
268 void Fuzzer::PrintStats(const char *Where, const char *End, size_t Units) {
269   size_t ExecPerSec = execPerSec();
270   if (!Options.Verbosity)
271     return;
272   Printf("#%zd\t%s", TotalNumberOfRuns, Where);
273   if (size_t N = TPC.GetTotalPCCoverage())
274     Printf(" cov: %zd", N);
275   if (size_t N = Corpus.NumFeatures())
276     Printf( " ft: %zd", N);
277   if (!Corpus.empty()) {
278     Printf(" corp: %zd", Corpus.NumActiveUnits());
279     if (size_t N = Corpus.SizeInBytes()) {
280       if (N < (1<<14))
281         Printf("/%zdb", N);
282       else if (N < (1 << 24))
283         Printf("/%zdKb", N >> 10);
284       else
285         Printf("/%zdMb", N >> 20);
286     }
287   }
288   if (Units)
289     Printf(" units: %zd", Units);
290 
291   Printf(" exec/s: %zd", ExecPerSec);
292   Printf(" rss: %zdMb", GetPeakRSSMb());
293   Printf("%s", End);
294 }
295 
296 void Fuzzer::PrintFinalStats() {
297   if (Options.PrintCoverage)
298     TPC.PrintCoverage();
299   if (Options.DumpCoverage)
300     TPC.DumpCoverage();
301   if (Options.PrintCorpusStats)
302     Corpus.PrintStats();
303   if (!Options.PrintFinalStats) return;
304   size_t ExecPerSec = execPerSec();
305   Printf("stat::number_of_executed_units: %zd\n", TotalNumberOfRuns);
306   Printf("stat::average_exec_per_sec:     %zd\n", ExecPerSec);
307   Printf("stat::new_units_added:          %zd\n", NumberOfNewUnitsAdded);
308   Printf("stat::slowest_unit_time_sec:    %zd\n", TimeOfLongestUnitInSeconds);
309   Printf("stat::peak_rss_mb:              %zd\n", GetPeakRSSMb());
310 }
311 
312 void Fuzzer::SetMaxInputLen(size_t MaxInputLen) {
313   assert(this->MaxInputLen == 0); // Can only reset MaxInputLen from 0 to non-0.
314   assert(MaxInputLen);
315   this->MaxInputLen = MaxInputLen;
316   this->MaxMutationLen = MaxInputLen;
317   AllocateCurrentUnitData();
318   Printf("INFO: -max_len is not provided; "
319          "libFuzzer will not generate inputs larger than %zd bytes\n",
320          MaxInputLen);
321 }
322 
323 void Fuzzer::SetMaxMutationLen(size_t MaxMutationLen) {
324   assert(MaxMutationLen && MaxMutationLen <= MaxInputLen);
325   this->MaxMutationLen = MaxMutationLen;
326 }
327 
328 void Fuzzer::CheckExitOnSrcPosOrItem() {
329   if (!Options.ExitOnSrcPos.empty()) {
330     static auto *PCsSet = new std::set<uintptr_t>;
331     auto HandlePC = [&](uintptr_t PC) {
332       if (!PCsSet->insert(PC).second) return;
333       std::string Descr = DescribePC("%F %L", PC + 1);
334       if (Descr.find(Options.ExitOnSrcPos) != std::string::npos) {
335         Printf("INFO: found line matching '%s', exiting.\n",
336                Options.ExitOnSrcPos.c_str());
337         _Exit(0);
338       }
339     };
340     TPC.ForEachObservedPC(HandlePC);
341   }
342   if (!Options.ExitOnItem.empty()) {
343     if (Corpus.HasUnit(Options.ExitOnItem)) {
344       Printf("INFO: found item with checksum '%s', exiting.\n",
345              Options.ExitOnItem.c_str());
346       _Exit(0);
347     }
348   }
349 }
350 
351 void Fuzzer::RereadOutputCorpus(size_t MaxSize) {
352   if (Options.OutputCorpus.empty() || !Options.ReloadIntervalSec) return;
353   std::vector<Unit> AdditionalCorpus;
354   ReadDirToVectorOfUnits(Options.OutputCorpus.c_str(), &AdditionalCorpus,
355                          &EpochOfLastReadOfOutputCorpus, MaxSize,
356                          /*ExitOnError*/ false);
357   if (Options.Verbosity >= 2)
358     Printf("Reload: read %zd new units.\n", AdditionalCorpus.size());
359   bool Reloaded = false;
360   for (auto &U : AdditionalCorpus) {
361     if (U.size() > MaxSize)
362       U.resize(MaxSize);
363     if (!Corpus.HasUnit(U)) {
364       if (RunOne(U.data(), U.size())) {
365         CheckExitOnSrcPosOrItem();
366         Reloaded = true;
367       }
368     }
369   }
370   if (Reloaded)
371     PrintStats("RELOAD");
372 }
373 
374 void Fuzzer::ShuffleCorpus(UnitVector *V) {
375   std::shuffle(V->begin(), V->end(), MD.GetRand());
376   if (Options.PreferSmall)
377     std::stable_sort(V->begin(), V->end(), [](const Unit &A, const Unit &B) {
378       return A.size() < B.size();
379     });
380 }
381 
382 void Fuzzer::ShuffleAndMinimize(UnitVector *InitialCorpus) {
383   Printf("#0\tREAD units: %zd\n", InitialCorpus->size());
384   if (Options.ShuffleAtStartUp)
385     ShuffleCorpus(InitialCorpus);
386 
387   // Test the callback with empty input and never try it again.
388   uint8_t dummy;
389   ExecuteCallback(&dummy, 0);
390 
391   for (auto &U : *InitialCorpus) {
392     RunOne(U.data(), U.size());
393     CheckExitOnSrcPosOrItem();
394     TryDetectingAMemoryLeak(U.data(), U.size(),
395                             /*DuringInitialCorpusExecution*/ true);
396     U.clear();
397   }
398   PrintStats("INITED");
399   if (Corpus.empty()) {
400     Printf("ERROR: no interesting inputs were found. "
401            "Is the code instrumented for coverage? Exiting.\n");
402     exit(1);
403   }
404 }
405 
406 void Fuzzer::PrintPulseAndReportSlowInput(const uint8_t *Data, size_t Size) {
407   auto TimeOfUnit =
408       duration_cast<seconds>(UnitStopTime - UnitStartTime).count();
409   if (!(TotalNumberOfRuns & (TotalNumberOfRuns - 1)) &&
410       secondsSinceProcessStartUp() >= 2)
411     PrintStats("pulse ");
412   if (TimeOfUnit > TimeOfLongestUnitInSeconds * 1.1 &&
413       TimeOfUnit >= Options.ReportSlowUnits) {
414     TimeOfLongestUnitInSeconds = TimeOfUnit;
415     Printf("Slowest unit: %zd s:\n", TimeOfLongestUnitInSeconds);
416     WriteUnitToFileWithPrefix({Data, Data + Size}, "slow-unit-");
417   }
418 }
419 
420 bool Fuzzer::RunOne(const uint8_t *Data, size_t Size, bool MayDeleteFile,
421                     InputInfo *II) {
422   if (!Size) return false;
423 
424   ExecuteCallback(Data, Size);
425 
426   UniqFeatureSetTmp.clear();
427   size_t FoundUniqFeaturesOfII = 0;
428   size_t NumUpdatesBefore = Corpus.NumFeatureUpdates();
429   TPC.CollectFeatures([&](size_t Feature) {
430     if (Corpus.AddFeature(Feature, Size, Options.Shrink))
431       UniqFeatureSetTmp.push_back(Feature);
432     if (Options.ReduceInputs && II)
433       if (std::binary_search(II->UniqFeatureSet.begin(),
434                              II->UniqFeatureSet.end(), Feature))
435         FoundUniqFeaturesOfII++;
436   });
437   PrintPulseAndReportSlowInput(Data, Size);
438   size_t NumNewFeatures = Corpus.NumFeatureUpdates() - NumUpdatesBefore;
439   if (NumNewFeatures) {
440     TPC.UpdateObservedPCs();
441     Corpus.AddToCorpus({Data, Data + Size}, NumNewFeatures, MayDeleteFile,
442                        UniqFeatureSetTmp);
443     return true;
444   }
445   if (II && FoundUniqFeaturesOfII &&
446       FoundUniqFeaturesOfII == II->UniqFeatureSet.size() &&
447       II->U.size() > Size) {
448     Corpus.Replace(II, {Data, Data + Size});
449     return true;
450   }
451   return false;
452 }
453 
454 size_t Fuzzer::GetCurrentUnitInFuzzingThead(const uint8_t **Data) const {
455   assert(InFuzzingThread());
456   *Data = CurrentUnitData;
457   return CurrentUnitSize;
458 }
459 
460 void Fuzzer::CrashOnOverwrittenData() {
461   Printf("==%d== ERROR: libFuzzer: fuzz target overwrites it's const input\n",
462          GetPid());
463   DumpCurrentUnit("crash-");
464   Printf("SUMMARY: libFuzzer: out-of-memory\n");
465   _Exit(Options.ErrorExitCode); // Stop right now.
466 }
467 
468 // Compare two arrays, but not all bytes if the arrays are large.
469 static bool LooseMemeq(const uint8_t *A, const uint8_t *B, size_t Size) {
470   const size_t Limit = 64;
471   if (Size <= 64)
472     return !memcmp(A, B, Size);
473   // Compare first and last Limit/2 bytes.
474   return !memcmp(A, B, Limit / 2) &&
475          !memcmp(A + Size - Limit / 2, B + Size - Limit / 2, Limit / 2);
476 }
477 
478 void Fuzzer::ExecuteCallback(const uint8_t *Data, size_t Size) {
479   TPC.RecordInitialStack();
480   TotalNumberOfRuns++;
481   assert(InFuzzingThread());
482   if (SMR.IsClient())
483     SMR.WriteByteArray(Data, Size);
484   // We copy the contents of Unit into a separate heap buffer
485   // so that we reliably find buffer overflows in it.
486   uint8_t *DataCopy = new uint8_t[Size];
487   memcpy(DataCopy, Data, Size);
488   if (CurrentUnitData && CurrentUnitData != Data)
489     memcpy(CurrentUnitData, Data, Size);
490   CurrentUnitSize = Size;
491   AllocTracer.Start(Options.TraceMalloc);
492   UnitStartTime = system_clock::now();
493   TPC.ResetMaps();
494   RunningCB = true;
495   int Res = CB(DataCopy, Size);
496   RunningCB = false;
497   UnitStopTime = system_clock::now();
498   (void)Res;
499   assert(Res == 0);
500   HasMoreMallocsThanFrees = AllocTracer.Stop();
501   if (!LooseMemeq(DataCopy, Data, Size))
502     CrashOnOverwrittenData();
503   CurrentUnitSize = 0;
504   delete[] DataCopy;
505 }
506 
507 void Fuzzer::WriteToOutputCorpus(const Unit &U) {
508   if (Options.OnlyASCII)
509     assert(IsASCII(U));
510   if (Options.OutputCorpus.empty())
511     return;
512   std::string Path = DirPlusFile(Options.OutputCorpus, Hash(U));
513   WriteToFile(U, Path);
514   if (Options.Verbosity >= 2)
515     Printf("Written %zd bytes to %s\n", U.size(), Path.c_str());
516 }
517 
518 void Fuzzer::WriteUnitToFileWithPrefix(const Unit &U, const char *Prefix) {
519   if (!Options.SaveArtifacts)
520     return;
521   std::string Path = Options.ArtifactPrefix + Prefix + Hash(U);
522   if (!Options.ExactArtifactPath.empty())
523     Path = Options.ExactArtifactPath; // Overrides ArtifactPrefix.
524   WriteToFile(U, Path);
525   Printf("artifact_prefix='%s'; Test unit written to %s\n",
526          Options.ArtifactPrefix.c_str(), Path.c_str());
527   if (U.size() <= kMaxUnitSizeToPrint)
528     Printf("Base64: %s\n", Base64(U).c_str());
529 }
530 
531 void Fuzzer::PrintStatusForNewUnit(const Unit &U, const char *Text) {
532   if (!Options.PrintNEW)
533     return;
534   PrintStats(Text, "");
535   if (Options.Verbosity) {
536     Printf(" L: %zd/%zd ", U.size(), Corpus.MaxInputSize());
537     MD.PrintMutationSequence();
538     Printf("\n");
539   }
540 }
541 
542 void Fuzzer::ReportNewCoverage(InputInfo *II, const Unit &U) {
543   II->NumSuccessfullMutations++;
544   MD.RecordSuccessfulMutationSequence();
545   PrintStatusForNewUnit(U, II->Reduced ? "REDUCE" :
546                                          "NEW   ");
547   WriteToOutputCorpus(U);
548   NumberOfNewUnitsAdded++;
549   CheckExitOnSrcPosOrItem();  // Check only after the unit is saved to corpus.
550   LastCorpusUpdateRun = TotalNumberOfRuns;
551   LastCorpusUpdateTime = system_clock::now();
552 }
553 
554 // Tries detecting a memory leak on the particular input that we have just
555 // executed before calling this function.
556 void Fuzzer::TryDetectingAMemoryLeak(const uint8_t *Data, size_t Size,
557                                      bool DuringInitialCorpusExecution) {
558   if (!HasMoreMallocsThanFrees) return;  // mallocs==frees, a leak is unlikely.
559   if (!Options.DetectLeaks) return;
560   if (!&(EF->__lsan_enable) || !&(EF->__lsan_disable) ||
561       !(EF->__lsan_do_recoverable_leak_check))
562     return;  // No lsan.
563   // Run the target once again, but with lsan disabled so that if there is
564   // a real leak we do not report it twice.
565   EF->__lsan_disable();
566   ExecuteCallback(Data, Size);
567   EF->__lsan_enable();
568   if (!HasMoreMallocsThanFrees) return;  // a leak is unlikely.
569   if (NumberOfLeakDetectionAttempts++ > 1000) {
570     Options.DetectLeaks = false;
571     Printf("INFO: libFuzzer disabled leak detection after every mutation.\n"
572            "      Most likely the target function accumulates allocated\n"
573            "      memory in a global state w/o actually leaking it.\n"
574            "      You may try running this binary with -trace_malloc=[12]"
575            "      to get a trace of mallocs and frees.\n"
576            "      If LeakSanitizer is enabled in this process it will still\n"
577            "      run on the process shutdown.\n");
578     return;
579   }
580   // Now perform the actual lsan pass. This is expensive and we must ensure
581   // we don't call it too often.
582   if (EF->__lsan_do_recoverable_leak_check()) { // Leak is found, report it.
583     if (DuringInitialCorpusExecution)
584       Printf("\nINFO: a leak has been found in the initial corpus.\n\n");
585     Printf("INFO: to ignore leaks on libFuzzer side use -detect_leaks=0.\n\n");
586     CurrentUnitSize = Size;
587     DumpCurrentUnit("leak-");
588     PrintFinalStats();
589     _Exit(Options.ErrorExitCode);  // not exit() to disable lsan further on.
590   }
591 }
592 
593 void Fuzzer::MutateAndTestOne() {
594   MD.StartMutationSequence();
595 
596   auto &II = Corpus.ChooseUnitToMutate(MD.GetRand());
597   const auto &U = II.U;
598   memcpy(BaseSha1, II.Sha1, sizeof(BaseSha1));
599   assert(CurrentUnitData);
600   size_t Size = U.size();
601   assert(Size <= MaxInputLen && "Oversized Unit");
602   memcpy(CurrentUnitData, U.data(), Size);
603 
604   assert(MaxMutationLen > 0);
605 
606   size_t CurrentMaxMutationLen =
607       Min(MaxMutationLen, Max(U.size(), TmpMaxMutationLen));
608   assert(CurrentMaxMutationLen > 0);
609 
610   for (int i = 0; i < Options.MutateDepth; i++) {
611     if (TotalNumberOfRuns >= Options.MaxNumberOfRuns)
612       break;
613     size_t NewSize = 0;
614     NewSize = MD.Mutate(CurrentUnitData, Size, CurrentMaxMutationLen);
615     assert(NewSize > 0 && "Mutator returned empty unit");
616     assert(NewSize <= CurrentMaxMutationLen && "Mutator return overisized unit");
617     Size = NewSize;
618     II.NumExecutedMutations++;
619     if (RunOne(CurrentUnitData, Size, /*MayDeleteFile=*/true, &II))
620       ReportNewCoverage(&II, {CurrentUnitData, CurrentUnitData + Size});
621 
622     TryDetectingAMemoryLeak(CurrentUnitData, Size,
623                             /*DuringInitialCorpusExecution*/ false);
624   }
625 }
626 
627 void Fuzzer::Loop() {
628   TPC.SetPrintNewPCs(Options.PrintNewCovPcs);
629   system_clock::time_point LastCorpusReload = system_clock::now();
630   if (Options.DoCrossOver)
631     MD.SetCorpus(&Corpus);
632   while (true) {
633     auto Now = system_clock::now();
634     if (duration_cast<seconds>(Now - LastCorpusReload).count() >=
635         Options.ReloadIntervalSec) {
636       RereadOutputCorpus(MaxInputLen);
637       LastCorpusReload = system_clock::now();
638     }
639     if (TotalNumberOfRuns >= Options.MaxNumberOfRuns)
640       break;
641     if (TimedOut()) break;
642 
643     // Update TmpMaxMutationLen
644     if (Options.ExperimentalLenControl) {
645       if (TmpMaxMutationLen < MaxMutationLen &&
646         (TotalNumberOfRuns - LastCorpusUpdateRun > 1000 &&
647         duration_cast<seconds>(Now - LastCorpusUpdateTime).count() >= 1)) {
648         LastCorpusUpdateRun = TotalNumberOfRuns;
649         LastCorpusUpdateTime = Now;
650         TmpMaxMutationLen =
651             Min(MaxMutationLen,
652                 TmpMaxMutationLen + Max(size_t(4), TmpMaxMutationLen / 8));
653         if (TmpMaxMutationLen <= MaxMutationLen)
654           Printf("#%zd\tTEMP_MAX_LEN: %zd\n", TotalNumberOfRuns,
655                  TmpMaxMutationLen);
656       }
657     } else {
658       TmpMaxMutationLen = MaxMutationLen;
659     }
660 
661     // Perform several mutations and runs.
662     MutateAndTestOne();
663   }
664 
665   PrintStats("DONE  ", "\n");
666   MD.PrintRecommendedDictionary();
667 }
668 
669 void Fuzzer::MinimizeCrashLoop(const Unit &U) {
670   if (U.size() <= 1) return;
671   while (!TimedOut() && TotalNumberOfRuns < Options.MaxNumberOfRuns) {
672     MD.StartMutationSequence();
673     memcpy(CurrentUnitData, U.data(), U.size());
674     for (int i = 0; i < Options.MutateDepth; i++) {
675       size_t NewSize = MD.Mutate(CurrentUnitData, U.size(), MaxMutationLen);
676       assert(NewSize > 0 && NewSize <= MaxMutationLen);
677       ExecuteCallback(CurrentUnitData, NewSize);
678       PrintPulseAndReportSlowInput(CurrentUnitData, NewSize);
679       TryDetectingAMemoryLeak(CurrentUnitData, NewSize,
680                               /*DuringInitialCorpusExecution*/ false);
681     }
682   }
683 }
684 
685 void Fuzzer::AnnounceOutput(const uint8_t *Data, size_t Size) {
686   if (SMR.IsServer()) {
687     SMR.WriteByteArray(Data, Size);
688   } else if (SMR.IsClient()) {
689     SMR.PostClient();
690     SMR.WaitServer();
691     size_t OtherSize = SMR.ReadByteArraySize();
692     uint8_t *OtherData = SMR.GetByteArray();
693     if (Size != OtherSize || memcmp(Data, OtherData, Size) != 0) {
694       size_t i = 0;
695       for (i = 0; i < Min(Size, OtherSize); i++)
696         if (Data[i] != OtherData[i])
697           break;
698       Printf("==%lu== ERROR: libFuzzer: equivalence-mismatch. Sizes: %zd %zd; "
699              "offset %zd\n", GetPid(), Size, OtherSize, i);
700       DumpCurrentUnit("mismatch-");
701       Printf("SUMMARY: libFuzzer: equivalence-mismatch\n");
702       PrintFinalStats();
703       _Exit(Options.ErrorExitCode);
704     }
705   }
706 }
707 
708 } // namespace fuzzer
709 
710 extern "C" {
711 
712 size_t LLVMFuzzerMutate(uint8_t *Data, size_t Size, size_t MaxSize) {
713   assert(fuzzer::F);
714   return fuzzer::F->GetMD().DefaultMutate(Data, Size, MaxSize);
715 }
716 
717 // Experimental
718 void LLVMFuzzerAnnounceOutput(const uint8_t *Data, size_t Size) {
719   assert(fuzzer::F);
720   fuzzer::F->AnnounceOutput(Data, Size);
721 }
722 }  // extern "C"
723