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 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   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::PrintPulseAndReportSlowInput(const uint8_t *Data, size_t Size) {
375   auto TimeOfUnit =
376       duration_cast<seconds>(UnitStopTime - UnitStartTime).count();
377   if (!(TotalNumberOfRuns & (TotalNumberOfRuns - 1)) &&
378       secondsSinceProcessStartUp() >= 2)
379     PrintStats("pulse ");
380   if (TimeOfUnit > TimeOfLongestUnitInSeconds * 1.1 &&
381       TimeOfUnit >= Options.ReportSlowUnits) {
382     TimeOfLongestUnitInSeconds = TimeOfUnit;
383     Printf("Slowest unit: %zd s:\n", TimeOfLongestUnitInSeconds);
384     WriteUnitToFileWithPrefix({Data, Data + Size}, "slow-unit-");
385   }
386 }
387 
388 bool Fuzzer::RunOne(const uint8_t *Data, size_t Size, bool MayDeleteFile,
389                     InputInfo *II) {
390   if (!Size) return false;
391 
392   ExecuteCallback(Data, Size);
393 
394   UniqFeatureSetTmp.clear();
395   size_t FoundUniqFeaturesOfII = 0;
396   size_t NumUpdatesBefore = Corpus.NumFeatureUpdates();
397   TPC.CollectFeatures([&](size_t Feature) {
398     if (Corpus.AddFeature(Feature, Size, Options.Shrink))
399       UniqFeatureSetTmp.push_back(Feature);
400     if (Options.ReduceInputs && II)
401       if (std::binary_search(II->UniqFeatureSet.begin(),
402                              II->UniqFeatureSet.end(), Feature))
403         FoundUniqFeaturesOfII++;
404   });
405   PrintPulseAndReportSlowInput(Data, Size);
406   size_t NumNewFeatures = Corpus.NumFeatureUpdates() - NumUpdatesBefore;
407   if (NumNewFeatures) {
408     TPC.UpdateObservedPCs();
409     Corpus.AddToCorpus({Data, Data + Size}, NumNewFeatures, MayDeleteFile,
410                        UniqFeatureSetTmp);
411     return true;
412   }
413   if (II && FoundUniqFeaturesOfII &&
414       FoundUniqFeaturesOfII == II->UniqFeatureSet.size() &&
415       II->U.size() > Size) {
416     Corpus.Replace(II, {Data, Data + Size});
417     return true;
418   }
419   return false;
420 }
421 
422 size_t Fuzzer::GetCurrentUnitInFuzzingThead(const uint8_t **Data) const {
423   assert(InFuzzingThread());
424   *Data = CurrentUnitData;
425   return CurrentUnitSize;
426 }
427 
428 void Fuzzer::CrashOnOverwrittenData() {
429   Printf("==%d== ERROR: libFuzzer: fuzz target overwrites it's const input\n",
430          GetPid());
431   DumpCurrentUnit("crash-");
432   Printf("SUMMARY: libFuzzer: out-of-memory\n");
433   _Exit(Options.ErrorExitCode); // Stop right now.
434 }
435 
436 // Compare two arrays, but not all bytes if the arrays are large.
437 static bool LooseMemeq(const uint8_t *A, const uint8_t *B, size_t Size) {
438   const size_t Limit = 64;
439   if (Size <= 64)
440     return !memcmp(A, B, Size);
441   // Compare first and last Limit/2 bytes.
442   return !memcmp(A, B, Limit / 2) &&
443          !memcmp(A + Size - Limit / 2, B + Size - Limit / 2, Limit / 2);
444 }
445 
446 void Fuzzer::ExecuteCallback(const uint8_t *Data, size_t Size) {
447   TPC.RecordInitialStack();
448   TotalNumberOfRuns++;
449   assert(InFuzzingThread());
450   if (SMR.IsClient())
451     SMR.WriteByteArray(Data, Size);
452   // We copy the contents of Unit into a separate heap buffer
453   // so that we reliably find buffer overflows in it.
454   uint8_t *DataCopy = new uint8_t[Size];
455   memcpy(DataCopy, Data, Size);
456   if (CurrentUnitData && CurrentUnitData != Data)
457     memcpy(CurrentUnitData, Data, Size);
458   CurrentUnitSize = Size;
459   AllocTracer.Start(Options.TraceMalloc);
460   UnitStartTime = system_clock::now();
461   TPC.ResetMaps();
462   RunningCB = true;
463   int Res = CB(DataCopy, Size);
464   RunningCB = false;
465   UnitStopTime = system_clock::now();
466   (void)Res;
467   assert(Res == 0);
468   HasMoreMallocsThanFrees = AllocTracer.Stop();
469   if (!LooseMemeq(DataCopy, Data, Size))
470     CrashOnOverwrittenData();
471   CurrentUnitSize = 0;
472   delete[] DataCopy;
473 }
474 
475 void Fuzzer::WriteToOutputCorpus(const Unit &U) {
476   if (Options.OnlyASCII)
477     assert(IsASCII(U));
478   if (Options.OutputCorpus.empty())
479     return;
480   std::string Path = DirPlusFile(Options.OutputCorpus, Hash(U));
481   WriteToFile(U, Path);
482   if (Options.Verbosity >= 2)
483     Printf("Written %zd bytes to %s\n", U.size(), Path.c_str());
484 }
485 
486 void Fuzzer::WriteUnitToFileWithPrefix(const Unit &U, const char *Prefix) {
487   if (!Options.SaveArtifacts)
488     return;
489   std::string Path = Options.ArtifactPrefix + Prefix + Hash(U);
490   if (!Options.ExactArtifactPath.empty())
491     Path = Options.ExactArtifactPath; // Overrides ArtifactPrefix.
492   WriteToFile(U, Path);
493   Printf("artifact_prefix='%s'; Test unit written to %s\n",
494          Options.ArtifactPrefix.c_str(), Path.c_str());
495   if (U.size() <= kMaxUnitSizeToPrint)
496     Printf("Base64: %s\n", Base64(U).c_str());
497 }
498 
499 void Fuzzer::PrintStatusForNewUnit(const Unit &U, const char *Text) {
500   if (!Options.PrintNEW)
501     return;
502   PrintStats(Text, "");
503   if (Options.Verbosity) {
504     Printf(" L: %zd/%zd ", U.size(), Corpus.MaxInputSize());
505     MD.PrintMutationSequence();
506     Printf("\n");
507   }
508 }
509 
510 void Fuzzer::ReportNewCoverage(InputInfo *II, const Unit &U) {
511   II->NumSuccessfullMutations++;
512   MD.RecordSuccessfulMutationSequence();
513   PrintStatusForNewUnit(U, II->Reduced ? "REDUCE" :
514                                          "NEW   ");
515   WriteToOutputCorpus(U);
516   NumberOfNewUnitsAdded++;
517   CheckExitOnSrcPosOrItem();  // Check only after the unit is saved to corpus.
518   LastCorpusUpdateRun = TotalNumberOfRuns;
519   LastCorpusUpdateTime = system_clock::now();
520 }
521 
522 // Tries detecting a memory leak on the particular input that we have just
523 // executed before calling this function.
524 void Fuzzer::TryDetectingAMemoryLeak(const uint8_t *Data, size_t Size,
525                                      bool DuringInitialCorpusExecution) {
526   if (!HasMoreMallocsThanFrees) return;  // mallocs==frees, a leak is unlikely.
527   if (!Options.DetectLeaks) return;
528   if (!DuringInitialCorpusExecution &&
529       TotalNumberOfRuns >= Options.MaxNumberOfRuns) return;
530   if (!&(EF->__lsan_enable) || !&(EF->__lsan_disable) ||
531       !(EF->__lsan_do_recoverable_leak_check))
532     return;  // No lsan.
533   // Run the target once again, but with lsan disabled so that if there is
534   // a real leak we do not report it twice.
535   EF->__lsan_disable();
536   ExecuteCallback(Data, Size);
537   EF->__lsan_enable();
538   if (!HasMoreMallocsThanFrees) return;  // a leak is unlikely.
539   if (NumberOfLeakDetectionAttempts++ > 1000) {
540     Options.DetectLeaks = false;
541     Printf("INFO: libFuzzer disabled leak detection after every mutation.\n"
542            "      Most likely the target function accumulates allocated\n"
543            "      memory in a global state w/o actually leaking it.\n"
544            "      You may try running this binary with -trace_malloc=[12]"
545            "      to get a trace of mallocs and frees.\n"
546            "      If LeakSanitizer is enabled in this process it will still\n"
547            "      run on the process shutdown.\n");
548     return;
549   }
550   // Now perform the actual lsan pass. This is expensive and we must ensure
551   // we don't call it too often.
552   if (EF->__lsan_do_recoverable_leak_check()) { // Leak is found, report it.
553     if (DuringInitialCorpusExecution)
554       Printf("\nINFO: a leak has been found in the initial corpus.\n\n");
555     Printf("INFO: to ignore leaks on libFuzzer side use -detect_leaks=0.\n\n");
556     CurrentUnitSize = Size;
557     DumpCurrentUnit("leak-");
558     PrintFinalStats();
559     _Exit(Options.ErrorExitCode);  // not exit() to disable lsan further on.
560   }
561 }
562 
563 void Fuzzer::MutateAndTestOne() {
564   MD.StartMutationSequence();
565 
566   auto &II = Corpus.ChooseUnitToMutate(MD.GetRand());
567   const auto &U = II.U;
568   memcpy(BaseSha1, II.Sha1, sizeof(BaseSha1));
569   assert(CurrentUnitData);
570   size_t Size = U.size();
571   assert(Size <= MaxInputLen && "Oversized Unit");
572   memcpy(CurrentUnitData, U.data(), Size);
573 
574   assert(MaxMutationLen > 0);
575 
576   size_t CurrentMaxMutationLen =
577       Min(MaxMutationLen, Max(U.size(), TmpMaxMutationLen));
578   assert(CurrentMaxMutationLen > 0);
579 
580   for (int i = 0; i < Options.MutateDepth; i++) {
581     if (TotalNumberOfRuns >= Options.MaxNumberOfRuns)
582       break;
583     size_t NewSize = 0;
584     NewSize = MD.Mutate(CurrentUnitData, Size, CurrentMaxMutationLen);
585     assert(NewSize > 0 && "Mutator returned empty unit");
586     assert(NewSize <= CurrentMaxMutationLen && "Mutator return overisized unit");
587     Size = NewSize;
588     II.NumExecutedMutations++;
589     if (RunOne(CurrentUnitData, Size, /*MayDeleteFile=*/true, &II))
590       ReportNewCoverage(&II, {CurrentUnitData, CurrentUnitData + Size});
591 
592     TryDetectingAMemoryLeak(CurrentUnitData, Size,
593                             /*DuringInitialCorpusExecution*/ false);
594   }
595 }
596 
597 void Fuzzer::ReadAndExecuteSeedCorpora(const Vector<std::string> &CorpusDirs) {
598   const size_t kMaxSaneLen = 1 << 20;
599   const size_t kMinDefaultLen = 4096;
600   Vector<SizedFile> SizedFiles;
601   size_t MaxSize = 0;
602   size_t MinSize = -1;
603   size_t TotalSize = 0;
604   size_t LastNumFiles = 0;
605   for (auto &Dir : CorpusDirs) {
606     GetSizedFilesFromDir(Dir, &SizedFiles);
607     Printf("INFO: % 8zd files found in %s\n", SizedFiles.size() - LastNumFiles,
608            Dir.c_str());
609     LastNumFiles = SizedFiles.size();
610   }
611   for (auto &File : SizedFiles) {
612     MaxSize = Max(File.Size, MaxSize);
613     MinSize = Min(File.Size, MinSize);
614     TotalSize += File.Size;
615   }
616   if (Options.MaxLen == 0)
617     SetMaxInputLen(std::min(std::max(kMinDefaultLen, MaxSize), kMaxSaneLen));
618   assert(MaxInputLen > 0);
619 
620   if (SizedFiles.empty()) {
621     Printf("INFO: A corpus is not provided, starting from an empty corpus\n");
622     Unit U({'\n'}); // Valid ASCII input.
623     RunOne(U.data(), U.size());
624   } else {
625     Printf("INFO: seed corpus: files: %zd min: %zdb max: %zdb total: %zdb"
626            " rss: %zdMb\n",
627            SizedFiles.size(), MinSize, MaxSize, TotalSize, GetPeakRSSMb());
628     if (Options.ShuffleAtStartUp)
629       std::shuffle(SizedFiles.begin(), SizedFiles.end(), MD.GetRand());
630 
631     if (Options.PreferSmall) {
632       std::stable_sort(SizedFiles.begin(), SizedFiles.end());
633       assert(SizedFiles.front().Size <= SizedFiles.back().Size);
634     }
635 
636     // Load and execute inputs one by one.
637     for (auto &SF : SizedFiles) {
638       auto U = FileToVector(SF.File, MaxInputLen, /*ExitOnError=*/false);
639       assert(U.size() <= MaxInputLen);
640       RunOne(U.data(), U.size());
641       CheckExitOnSrcPosOrItem();
642       TryDetectingAMemoryLeak(U.data(), U.size(),
643                               /*DuringInitialCorpusExecution*/ true);
644     }
645   }
646 
647   // Test the callback with empty input and never try it again.
648   uint8_t dummy;
649   ExecuteCallback(&dummy, 0);
650 
651   PrintStats("INITED");
652   if (Corpus.empty()) {
653     Printf("ERROR: no interesting inputs were found. "
654            "Is the code instrumented for coverage? Exiting.\n");
655     exit(1);
656   }
657 }
658 
659 void Fuzzer::Loop(const Vector<std::string> &CorpusDirs) {
660   ReadAndExecuteSeedCorpora(CorpusDirs);
661   TPC.SetPrintNewPCs(Options.PrintNewCovPcs);
662   TPC.SetPrintNewFuncs(Options.PrintNewCovFuncs);
663   system_clock::time_point LastCorpusReload = system_clock::now();
664   if (Options.DoCrossOver)
665     MD.SetCorpus(&Corpus);
666   while (true) {
667     auto Now = system_clock::now();
668     if (duration_cast<seconds>(Now - LastCorpusReload).count() >=
669         Options.ReloadIntervalSec) {
670       RereadOutputCorpus(MaxInputLen);
671       LastCorpusReload = system_clock::now();
672     }
673     if (TotalNumberOfRuns >= Options.MaxNumberOfRuns)
674       break;
675     if (TimedOut()) break;
676 
677     // Update TmpMaxMutationLen
678     if (Options.ExperimentalLenControl) {
679       if (TmpMaxMutationLen < MaxMutationLen &&
680         (TotalNumberOfRuns - LastCorpusUpdateRun > 1000 &&
681         duration_cast<seconds>(Now - LastCorpusUpdateTime).count() >= 1)) {
682         LastCorpusUpdateRun = TotalNumberOfRuns;
683         LastCorpusUpdateTime = Now;
684         TmpMaxMutationLen =
685             Min(MaxMutationLen,
686                 TmpMaxMutationLen + Max(size_t(4), TmpMaxMutationLen / 8));
687         if (TmpMaxMutationLen <= MaxMutationLen)
688           Printf("#%zd\tTEMP_MAX_LEN: %zd\n", TotalNumberOfRuns,
689                  TmpMaxMutationLen);
690       }
691     } else {
692       TmpMaxMutationLen = MaxMutationLen;
693     }
694 
695     // Perform several mutations and runs.
696     MutateAndTestOne();
697   }
698 
699   PrintStats("DONE  ", "\n");
700   MD.PrintRecommendedDictionary();
701 }
702 
703 void Fuzzer::MinimizeCrashLoop(const Unit &U) {
704   if (U.size() <= 1) return;
705   while (!TimedOut() && TotalNumberOfRuns < Options.MaxNumberOfRuns) {
706     MD.StartMutationSequence();
707     memcpy(CurrentUnitData, U.data(), U.size());
708     for (int i = 0; i < Options.MutateDepth; i++) {
709       size_t NewSize = MD.Mutate(CurrentUnitData, U.size(), MaxMutationLen);
710       assert(NewSize > 0 && NewSize <= MaxMutationLen);
711       ExecuteCallback(CurrentUnitData, NewSize);
712       PrintPulseAndReportSlowInput(CurrentUnitData, NewSize);
713       TryDetectingAMemoryLeak(CurrentUnitData, NewSize,
714                               /*DuringInitialCorpusExecution*/ false);
715     }
716   }
717 }
718 
719 void Fuzzer::AnnounceOutput(const uint8_t *Data, size_t Size) {
720   if (SMR.IsServer()) {
721     SMR.WriteByteArray(Data, Size);
722   } else if (SMR.IsClient()) {
723     SMR.PostClient();
724     SMR.WaitServer();
725     size_t OtherSize = SMR.ReadByteArraySize();
726     uint8_t *OtherData = SMR.GetByteArray();
727     if (Size != OtherSize || memcmp(Data, OtherData, Size) != 0) {
728       size_t i = 0;
729       for (i = 0; i < Min(Size, OtherSize); i++)
730         if (Data[i] != OtherData[i])
731           break;
732       Printf("==%lu== ERROR: libFuzzer: equivalence-mismatch. Sizes: %zd %zd; "
733              "offset %zd\n", GetPid(), Size, OtherSize, i);
734       DumpCurrentUnit("mismatch-");
735       Printf("SUMMARY: libFuzzer: equivalence-mismatch\n");
736       PrintFinalStats();
737       _Exit(Options.ErrorExitCode);
738     }
739   }
740 }
741 
742 } // namespace fuzzer
743 
744 extern "C" {
745 
746 size_t LLVMFuzzerMutate(uint8_t *Data, size_t Size, size_t MaxSize) {
747   assert(fuzzer::F);
748   return fuzzer::F->GetMD().DefaultMutate(Data, Size, MaxSize);
749 }
750 
751 // Experimental
752 void LLVMFuzzerAnnounceOutput(const uint8_t *Data, size_t Size) {
753   assert(fuzzer::F);
754   fuzzer::F->AnnounceOutput(Data, Size);
755 }
756 }  // extern "C"
757