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 (!&(EF->__lsan_enable) || !&(EF->__lsan_disable) ||
529       !(EF->__lsan_do_recoverable_leak_check))
530     return;  // No lsan.
531   // Run the target once again, but with lsan disabled so that if there is
532   // a real leak we do not report it twice.
533   EF->__lsan_disable();
534   ExecuteCallback(Data, Size);
535   EF->__lsan_enable();
536   if (!HasMoreMallocsThanFrees) return;  // a leak is unlikely.
537   if (NumberOfLeakDetectionAttempts++ > 1000) {
538     Options.DetectLeaks = false;
539     Printf("INFO: libFuzzer disabled leak detection after every mutation.\n"
540            "      Most likely the target function accumulates allocated\n"
541            "      memory in a global state w/o actually leaking it.\n"
542            "      You may try running this binary with -trace_malloc=[12]"
543            "      to get a trace of mallocs and frees.\n"
544            "      If LeakSanitizer is enabled in this process it will still\n"
545            "      run on the process shutdown.\n");
546     return;
547   }
548   // Now perform the actual lsan pass. This is expensive and we must ensure
549   // we don't call it too often.
550   if (EF->__lsan_do_recoverable_leak_check()) { // Leak is found, report it.
551     if (DuringInitialCorpusExecution)
552       Printf("\nINFO: a leak has been found in the initial corpus.\n\n");
553     Printf("INFO: to ignore leaks on libFuzzer side use -detect_leaks=0.\n\n");
554     CurrentUnitSize = Size;
555     DumpCurrentUnit("leak-");
556     PrintFinalStats();
557     _Exit(Options.ErrorExitCode);  // not exit() to disable lsan further on.
558   }
559 }
560 
561 void Fuzzer::MutateAndTestOne() {
562   MD.StartMutationSequence();
563 
564   auto &II = Corpus.ChooseUnitToMutate(MD.GetRand());
565   const auto &U = II.U;
566   memcpy(BaseSha1, II.Sha1, sizeof(BaseSha1));
567   assert(CurrentUnitData);
568   size_t Size = U.size();
569   assert(Size <= MaxInputLen && "Oversized Unit");
570   memcpy(CurrentUnitData, U.data(), Size);
571 
572   assert(MaxMutationLen > 0);
573 
574   size_t CurrentMaxMutationLen =
575       Min(MaxMutationLen, Max(U.size(), TmpMaxMutationLen));
576   assert(CurrentMaxMutationLen > 0);
577 
578   for (int i = 0; i < Options.MutateDepth; i++) {
579     if (TotalNumberOfRuns >= Options.MaxNumberOfRuns)
580       break;
581     size_t NewSize = 0;
582     NewSize = MD.Mutate(CurrentUnitData, Size, CurrentMaxMutationLen);
583     assert(NewSize > 0 && "Mutator returned empty unit");
584     assert(NewSize <= CurrentMaxMutationLen && "Mutator return overisized unit");
585     Size = NewSize;
586     II.NumExecutedMutations++;
587     if (RunOne(CurrentUnitData, Size, /*MayDeleteFile=*/true, &II))
588       ReportNewCoverage(&II, {CurrentUnitData, CurrentUnitData + Size});
589 
590     TryDetectingAMemoryLeak(CurrentUnitData, Size,
591                             /*DuringInitialCorpusExecution*/ false);
592   }
593 }
594 
595 void Fuzzer::ReadAndExecuteSeedCorpora(const Vector<std::string> &CorpusDirs) {
596   const size_t kMaxSaneLen = 1 << 20;
597   const size_t kMinDefaultLen = 4096;
598   struct SizedFile {
599     std::string File;
600     size_t Size;
601   };
602   Vector<SizedFile> SizedFiles;
603   size_t MaxSize = 0;
604   size_t MinSize = -1;
605   size_t TotalSize = 0;
606   for (auto &Dir : CorpusDirs) {
607     Vector<std::string> Files;
608     ListFilesInDirRecursive(Dir, 0, &Files, /*TopDir*/true);
609     Printf("INFO: % 8zd files found in %s\n", Files.size(), Dir.c_str());
610     for (auto &File : Files) {
611       if (size_t Size = FileSize(File)) {
612         MaxSize = Max(Size, MaxSize);
613         MinSize = Min(Size, MinSize);
614         TotalSize += Size;
615         SizedFiles.push_back({File, Size});
616       }
617     }
618   }
619   if (Options.MaxLen == 0)
620     SetMaxInputLen(std::min(std::max(kMinDefaultLen, MaxSize), kMaxSaneLen));
621   assert(MaxInputLen > 0);
622 
623   if (SizedFiles.empty()) {
624     Printf("INFO: A corpus is not provided, starting from an empty corpus\n");
625     Unit U({'\n'}); // Valid ASCII input.
626     RunOne(U.data(), U.size());
627   } else {
628     Printf("INFO: seed corpus: files: %zd min: %zdb max: %zdb total: %zdb"
629            " rss: %zdMb\n",
630            SizedFiles.size(), MinSize, MaxSize, TotalSize, GetPeakRSSMb());
631     if (Options.ShuffleAtStartUp)
632       std::shuffle(SizedFiles.begin(), SizedFiles.end(), MD.GetRand());
633 
634     if (Options.PreferSmall)
635       std::stable_sort(
636           SizedFiles.begin(), SizedFiles.end(),
637           [](const SizedFile &A, const SizedFile &B) { return A.Size < B.Size; });
638 
639     // Load and execute inputs one by one.
640     for (auto &SF : SizedFiles) {
641       auto U = FileToVector(SF.File, MaxInputLen, /*ExitOnError=*/false);
642       assert(U.size() <= MaxInputLen);
643       RunOne(U.data(), U.size());
644       CheckExitOnSrcPosOrItem();
645       TryDetectingAMemoryLeak(U.data(), U.size(),
646                               /*DuringInitialCorpusExecution*/ true);
647     }
648   }
649 
650   // Test the callback with empty input and never try it again.
651   uint8_t dummy;
652   ExecuteCallback(&dummy, 0);
653 
654   PrintStats("INITED");
655   if (Corpus.empty()) {
656     Printf("ERROR: no interesting inputs were found. "
657            "Is the code instrumented for coverage? Exiting.\n");
658     exit(1);
659   }
660 }
661 
662 void Fuzzer::Loop(const Vector<std::string> &CorpusDirs) {
663   ReadAndExecuteSeedCorpora(CorpusDirs);
664   TPC.SetPrintNewPCs(Options.PrintNewCovPcs);
665   TPC.SetPrintNewFuncs(Options.PrintNewCovFuncs);
666   system_clock::time_point LastCorpusReload = system_clock::now();
667   if (Options.DoCrossOver)
668     MD.SetCorpus(&Corpus);
669   while (true) {
670     auto Now = system_clock::now();
671     if (duration_cast<seconds>(Now - LastCorpusReload).count() >=
672         Options.ReloadIntervalSec) {
673       RereadOutputCorpus(MaxInputLen);
674       LastCorpusReload = system_clock::now();
675     }
676     if (TotalNumberOfRuns >= Options.MaxNumberOfRuns)
677       break;
678     if (TimedOut()) break;
679 
680     // Update TmpMaxMutationLen
681     if (Options.ExperimentalLenControl) {
682       if (TmpMaxMutationLen < MaxMutationLen &&
683         (TotalNumberOfRuns - LastCorpusUpdateRun > 1000 &&
684         duration_cast<seconds>(Now - LastCorpusUpdateTime).count() >= 1)) {
685         LastCorpusUpdateRun = TotalNumberOfRuns;
686         LastCorpusUpdateTime = Now;
687         TmpMaxMutationLen =
688             Min(MaxMutationLen,
689                 TmpMaxMutationLen + Max(size_t(4), TmpMaxMutationLen / 8));
690         if (TmpMaxMutationLen <= MaxMutationLen)
691           Printf("#%zd\tTEMP_MAX_LEN: %zd\n", TotalNumberOfRuns,
692                  TmpMaxMutationLen);
693       }
694     } else {
695       TmpMaxMutationLen = MaxMutationLen;
696     }
697 
698     // Perform several mutations and runs.
699     MutateAndTestOne();
700   }
701 
702   PrintStats("DONE  ", "\n");
703   MD.PrintRecommendedDictionary();
704 }
705 
706 void Fuzzer::MinimizeCrashLoop(const Unit &U) {
707   if (U.size() <= 1) return;
708   while (!TimedOut() && TotalNumberOfRuns < Options.MaxNumberOfRuns) {
709     MD.StartMutationSequence();
710     memcpy(CurrentUnitData, U.data(), U.size());
711     for (int i = 0; i < Options.MutateDepth; i++) {
712       size_t NewSize = MD.Mutate(CurrentUnitData, U.size(), MaxMutationLen);
713       assert(NewSize > 0 && NewSize <= MaxMutationLen);
714       ExecuteCallback(CurrentUnitData, NewSize);
715       PrintPulseAndReportSlowInput(CurrentUnitData, NewSize);
716       TryDetectingAMemoryLeak(CurrentUnitData, NewSize,
717                               /*DuringInitialCorpusExecution*/ false);
718     }
719   }
720 }
721 
722 void Fuzzer::AnnounceOutput(const uint8_t *Data, size_t Size) {
723   if (SMR.IsServer()) {
724     SMR.WriteByteArray(Data, Size);
725   } else if (SMR.IsClient()) {
726     SMR.PostClient();
727     SMR.WaitServer();
728     size_t OtherSize = SMR.ReadByteArraySize();
729     uint8_t *OtherData = SMR.GetByteArray();
730     if (Size != OtherSize || memcmp(Data, OtherData, Size) != 0) {
731       size_t i = 0;
732       for (i = 0; i < Min(Size, OtherSize); i++)
733         if (Data[i] != OtherData[i])
734           break;
735       Printf("==%lu== ERROR: libFuzzer: equivalence-mismatch. Sizes: %zd %zd; "
736              "offset %zd\n", GetPid(), Size, OtherSize, i);
737       DumpCurrentUnit("mismatch-");
738       Printf("SUMMARY: libFuzzer: equivalence-mismatch\n");
739       PrintFinalStats();
740       _Exit(Options.ErrorExitCode);
741     }
742   }
743 }
744 
745 } // namespace fuzzer
746 
747 extern "C" {
748 
749 size_t LLVMFuzzerMutate(uint8_t *Data, size_t Size, size_t MaxSize) {
750   assert(fuzzer::F);
751   return fuzzer::F->GetMD().DefaultMutate(Data, Size, MaxSize);
752 }
753 
754 // Experimental
755 void LLVMFuzzerAnnounceOutput(const uint8_t *Data, size_t Size) {
756   assert(fuzzer::F);
757   fuzzer::F->AnnounceOutput(Data, Size);
758 }
759 }  // extern "C"
760