1 //===- FuzzerLoop.cpp - Fuzzer's main loop --------------------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 //===----------------------------------------------------------------------===//
12 #include "FuzzerCorpus.h"
13 #include "FuzzerInternal.h"
15 #include "FuzzerMutate.h"
16 #include "FuzzerRandom.h"
17 #include "FuzzerTracePC.h"
23 #if defined(__has_include)
24 #if __has_include(<sanitizer / coverage_interface.h>)
25 #include <sanitizer/coverage_interface.h>
27 #if __has_include(<sanitizer / lsan_interface.h>)
28 #include <sanitizer/lsan_interface.h>
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))
41 static const size_t kMaxUnitSizeToPrint = 256;
43 thread_local bool Fuzzer::IsMyThread;
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",
52 #define CHECK_EXTERNAL_FUNCTION(fn) \
55 MissingExternalApiFunction(#fn); \
58 // Only one Fuzzer per process.
61 void Fuzzer::ResetEdgeCoverage() {
62 CHECK_EXTERNAL_FUNCTION(__sanitizer_reset_coverage);
63 EF->__sanitizer_reset_coverage();
66 void Fuzzer::ResetCounters() {
67 if (Options.UseCounters)
68 EF->__sanitizer_update_counter_bitset_and_clear_counters(0);
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);
78 // Records data to a maximum coverage tracker. Returns true if additional
79 // coverage was discovered.
80 bool Fuzzer::RecordMaxCoverage(Fuzzer::Coverage *C) {
83 uint64_t NewBlockCoverage = EF->__sanitizer_get_total_unique_coverage();
84 if (NewBlockCoverage > C->BlockCoverage) {
86 C->BlockCoverage = NewBlockCoverage;
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) {
95 C->CallerCalleeCoverage = NewCallerCalleeCoverage;
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) {
105 C->CounterBitmapBits += CounterDelta;
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 {
115 void Start(int TraceLevel) {
116 this->TraceLevel = TraceLevel;
118 Printf("MallocFreeTracer: START\n");
122 // Returns true if there were more mallocs than frees.
125 Printf("MallocFreeTracer: STOP %zd %zd (%s)\n", Mallocs.load(),
126 Frees.load(), Mallocs == Frees ? "same" : "DIFFERENT");
127 bool Result = Mallocs > Frees;
133 std::atomic<size_t> Mallocs;
134 std::atomic<size_t> Frees;
138 static MallocFreeTracer AllocTracer;
140 ATTRIBUTE_NO_SANITIZE_MEMORY
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();
151 ATTRIBUTE_NO_SANITIZE_MEMORY
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();
161 // Crash on a single malloc that exceeds the rss limit.
162 void Fuzzer::HandleMalloc(size_t Size) {
163 if (!Options.RssLimitMb || (Size >> 20) < (size_t)Options.RssLimitMb)
165 Printf("==%d== ERROR: libFuzzer: out-of-memory (malloc(%zd))\n", GetPid(),
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");
173 _Exit(Options.ErrorExitCode); // Stop right now.
176 Fuzzer::Fuzzer(UserCallback CB, InputCorpus &Corpus, MutationDispatcher &MD,
177 FuzzingOptions Options)
178 : CB(CB), Corpus(Corpus), MD(MD), Options(Options) {
180 InitializeTraceState();
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);
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();
199 memset(BaseSha1, 0, sizeof(BaseSha1));
202 Fuzzer::~Fuzzer() { }
204 void Fuzzer::AllocateCurrentUnitData() {
205 if (CurrentUnitData || MaxInputLen == 0) return;
206 CurrentUnitData = new uint8_t[MaxInputLen];
209 void Fuzzer::SetDeathCallback() {
210 CHECK_EXTERNAL_FUNCTION(__sanitizer_set_death_callback);
211 EF->__sanitizer_set_death_callback(StaticDeathCallback);
214 void Fuzzer::StaticDeathCallback() {
219 static void WarnOnUnsuccessfullMerge(bool DoWarn) {
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"
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");
244 WriteUnitToFileWithPrefix({CurrentUnitData, CurrentUnitData + UnitSize},
249 void Fuzzer::DeathCallback() {
250 DumpCurrentUnit("crash-");
254 void Fuzzer::StaticAlarmCallback() {
259 void Fuzzer::StaticCrashSignalCallback() {
264 void Fuzzer::StaticInterruptCallback() {
266 F->InterruptCallback();
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 "
276 Printf("SUMMARY: libFuzzer: deadly signal\n");
277 DumpCurrentUnit("crash-");
279 exit(Options.ErrorExitCode);
282 void Fuzzer::InterruptCallback() {
283 Printf("==%lu== libFuzzer: run interrupted; exiting\n", GetPid());
285 _Exit(0); // Stop right now, don't perform any at-exit actions.
289 void Fuzzer::AlarmCallback() {
290 assert(Options.UnitTimeoutSec > 0);
291 if (!InFuzzingThread()) return;
293 return; // We have not started running units yet.
295 duration_cast<seconds>(system_clock::now() - UnitStartTime).count();
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(),
307 if (EF->__sanitizer_print_stack_trace)
308 EF->__sanitizer_print_stack_trace();
309 Printf("SUMMARY: libFuzzer: timeout\n");
311 _Exit(Options.TimeoutExitCode); // Stop right now.
315 void Fuzzer::RssLimitCallback() {
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");
325 _Exit(Options.ErrorExitCode); // Stop right now.
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");
336 Printf("%zd,%zd,%zd,%zd,%zd,%zd,%s\n", TotalNumberOfRuns,
337 MaxCoverage.BlockCoverage, MaxCoverage.CounterBitmapBits,
338 MaxCoverage.CallerCalleeCoverage, Corpus.size(), ExecPerSec, Where);
341 if (!Options.Verbosity)
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()) {
361 else if (N < (1 << 24))
362 Printf("/%zdKb", N >> 10);
364 Printf("/%zdMb", N >> 20);
368 Printf(" units: %zd", Units);
370 Printf(" exec/s: %zd", ExecPerSec);
371 Printf(" rss: %zdMb", GetPeakRSSMb());
375 void Fuzzer::PrintFinalStats() {
376 if (Options.PrintCoverage)
378 if (Options.DumpCoverage)
380 if (Options.PrintCorpusStats)
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());
391 void Fuzzer::SetMaxInputLen(size_t MaxInputLen) {
392 assert(this->MaxInputLen == 0); // Can only reset MaxInputLen from 0 to non-0.
394 this->MaxInputLen = MaxInputLen;
395 this->MaxMutationLen = MaxInputLen;
396 AllocateCurrentUnitData();
397 Printf("INFO: -max_len is not provided, using %zd\n", MaxInputLen);
400 void Fuzzer::SetMaxMutationLen(size_t MaxMutationLen) {
401 assert(MaxMutationLen && MaxMutationLen <= MaxInputLen);
402 this->MaxMutationLen = MaxMutationLen;
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);
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());
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());
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)
441 if (!Corpus.HasUnit(U)) {
442 if (size_t NumFeatures = RunOne(U)) {
443 CheckExitOnSrcPosOrItem();
444 Corpus.AddToCorpus(U, NumFeatures);
450 PrintStats("RELOAD");
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();
461 void Fuzzer::ShuffleAndMinimize(UnitVector *InitialCorpus) {
462 Printf("#0\tREAD units: %zd\n", InitialCorpus->size());
463 if (Options.ShuffleAtStartUp)
464 ShuffleCorpus(InitialCorpus);
466 // Test the callback with empty input and never try it again.
468 ExecuteCallback(&dummy, 0);
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());
477 TryDetectingAMemoryLeak(U.data(), U.size(),
478 /*DuringInitialCorpusExecution*/ true);
480 PrintStats("INITED");
481 if (Corpus.empty()) {
482 Printf("ERROR: no interesting inputs were found. "
483 "Is the code instrumented for coverage? Exiting.\n");
488 size_t Fuzzer::RunOne(const uint8_t *Data, size_t Size) {
492 ExecuteCallback(Data, Size);
495 if (size_t NumFeatures = TPC.CollectFeatures([&](size_t Feature) -> bool {
496 return Corpus.AddFeature(Feature, Size, Options.Shrink);
500 if (!TPC.UsingTracePcGuard()) {
501 if (TPC.UpdateValueProfileMap(&MaxCoverage.VPMap))
503 if (!Res && RecordMaxCoverage(&MaxCoverage))
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-");
521 size_t Fuzzer::GetCurrentUnitInFuzzingThead(const uint8_t **Data) const {
522 assert(InFuzzingThread());
523 *Data = CurrentUnitData;
524 return CurrentUnitSize;
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.
541 int Res = CB(DataCopy, Size);
543 UnitStopTime = system_clock::now();
546 HasMoreMallocsThanFrees = AllocTracer.Stop();
551 void Fuzzer::WriteToOutputCorpus(const Unit &U) {
552 if (Options.OnlyASCII)
554 if (Options.OutputCorpus.empty())
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());
562 void Fuzzer::WriteUnitToFileWithPrefix(const Unit &U, const char *Prefix) {
563 if (!Options.SaveArtifacts)
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());
575 void Fuzzer::PrintStatusForNewUnit(const Unit &U) {
576 if (!Options.PrintNEW)
578 PrintStats("NEW ", "");
579 if (Options.Verbosity) {
580 Printf(" L: %zd ", U.size());
581 MD.PrintMutationSequence();
586 void Fuzzer::ReportNewCoverage(InputInfo *II, const Unit &U) {
587 II->NumSuccessfullMutations++;
588 MD.RecordSuccessfulMutationSequence();
589 PrintStatusForNewUnit(U);
590 WriteToOutputCorpus(U);
591 NumberOfNewUnitsAdded++;
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".
599 UnitVector Fuzzer::FindExtraUnits(const UnitVector &Initial,
600 const UnitVector &Extra) {
601 UnitVector Res = Extra;
603 size_t OldSize = Res.size();
604 for (int Iter = 0; Iter < 10; Iter++) {
607 Corpus.ResetFeatureSet();
610 for (auto &U : Initial) {
616 for (auto &U : Res) {
622 char Stat[7] = "MIN ";
623 Stat[3] = '0' + Iter;
624 PrintStats(Stat, "\n", Tmp.size());
626 size_t NewSize = Tmp.size();
627 assert(NewSize <= OldSize);
630 if (NewSize + 5 >= OldSize)
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");
643 std::vector<std::string> ExtraCorpora(Corpora.begin() + 1, Corpora.end());
645 assert(MaxInputLen > 0);
646 UnitVector Initial, Extra;
647 ReadDirToVectorOfUnits(Corpora[0].c_str(), &Initial, nullptr, MaxInputLen,
649 for (auto &C : ExtraCorpora)
650 ReadDirToVectorOfUnits(C.c_str(), &Extra, nullptr, MaxInputLen, true);
652 if (!Initial.empty()) {
653 Printf("=== Minimizing the initial corpus of %zd units\n", Initial.size());
654 Initial = FindExtraUnits({}, Initial);
657 Printf("=== Merging extra %zd units\n", Extra.size());
658 auto Res = FindExtraUnits(Initial, Extra);
661 WriteToOutputCorpus(U);
663 Printf("=== Merge: written %zd units\n", Res.size());
666 // Tries detecting a memory leak on the particular input that we have just
667 // executed before calling this function.
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))
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);
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");
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-");
701 _Exit(Options.ErrorExitCode); // not exit() to disable lsan further on.
705 static size_t ComputeMutationLen(size_t MaxInputSize, size_t MaxMutationLen,
707 assert(MaxInputSize <= MaxMutationLen);
708 if (MaxInputSize == MaxMutationLen) return MaxMutationLen;
709 size_t Result = MaxInputSize;
710 size_t R = Rand.Rand();
711 if ((R % (1U << 7)) == 0)
713 if ((R % (1U << 15)) == 0)
714 Result += 10 + Result / 2;
715 return Min(Result, MaxMutationLen);
718 void Fuzzer::MutateAndTestOne() {
719 MD.StartMutationSequence();
721 auto &II = Corpus.ChooseUnitToMutate(MD.GetRand());
722 const auto &U = II.U;
723 memcpy(BaseSha1, II.Sha1, sizeof(BaseSha1));
724 assert(CurrentUnitData);
725 size_t Size = U.size();
726 assert(Size <= MaxInputLen && "Oversized Unit");
727 memcpy(CurrentUnitData, U.data(), Size);
729 assert(MaxMutationLen > 0);
731 size_t CurrentMaxMutationLen =
732 Options.ExperimentalLenControl
733 ? ComputeMutationLen(Corpus.MaxInputSize(), MaxMutationLen,
737 for (int i = 0; i < Options.MutateDepth; i++) {
738 if (TotalNumberOfRuns >= Options.MaxNumberOfRuns)
741 NewSize = MD.Mutate(CurrentUnitData, Size, CurrentMaxMutationLen);
742 assert(NewSize > 0 && "Mutator returned empty unit");
743 assert(NewSize <= CurrentMaxMutationLen && "Mutator return overisized unit");
746 StartTraceRecording();
747 II.NumExecutedMutations++;
748 if (size_t NumFeatures = RunOne(CurrentUnitData, Size)) {
749 Corpus.AddToCorpus({CurrentUnitData, CurrentUnitData + Size}, NumFeatures,
750 /*MayDeleteFile=*/true);
751 ReportNewCoverage(&II, {CurrentUnitData, CurrentUnitData + Size});
752 CheckExitOnSrcPosOrItem();
754 StopTraceRecording();
755 TryDetectingAMemoryLeak(CurrentUnitData, Size,
756 /*DuringInitialCorpusExecution*/ false);
760 void Fuzzer::ResetCoverage() {
763 PrepareCounters(&MaxCoverage);
766 void Fuzzer::Loop() {
767 TPC.InitializePrintNewPCs();
768 system_clock::time_point LastCorpusReload = system_clock::now();
769 if (Options.DoCrossOver)
770 MD.SetCorpus(&Corpus);
772 auto Now = system_clock::now();
773 if (duration_cast<seconds>(Now - LastCorpusReload).count() >=
774 Options.ReloadIntervalSec) {
775 RereadOutputCorpus(MaxInputLen);
776 LastCorpusReload = system_clock::now();
778 if (TotalNumberOfRuns >= Options.MaxNumberOfRuns)
780 if (TimedOut()) break;
781 // Perform several mutations and runs.
785 PrintStats("DONE ", "\n");
786 MD.PrintRecommendedDictionary();
789 void Fuzzer::MinimizeCrashLoop(const Unit &U) {
790 if (U.size() <= 2) return;
791 while (!TimedOut() && TotalNumberOfRuns < Options.MaxNumberOfRuns) {
792 MD.StartMutationSequence();
793 memcpy(CurrentUnitData, U.data(), U.size());
794 for (int i = 0; i < Options.MutateDepth; i++) {
795 size_t NewSize = MD.Mutate(CurrentUnitData, U.size(), MaxMutationLen);
796 assert(NewSize > 0 && NewSize <= MaxMutationLen);
797 RunOne(CurrentUnitData, NewSize);
798 TryDetectingAMemoryLeak(CurrentUnitData, NewSize,
799 /*DuringInitialCorpusExecution*/ false);
804 } // namespace fuzzer
808 size_t LLVMFuzzerMutate(uint8_t *Data, size_t Size, size_t MaxSize) {
810 return fuzzer::F->GetMD().DefaultMutate(Data, Size, MaxSize);