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