14ba319b5SDimitry Andric //===- FuzzerLoop.cpp - Fuzzer's main loop --------------------------------===//
24ba319b5SDimitry Andric //
34ba319b5SDimitry Andric //                     The LLVM Compiler Infrastructure
44ba319b5SDimitry Andric //
54ba319b5SDimitry Andric // This file is distributed under the University of Illinois Open Source
64ba319b5SDimitry Andric // License. See LICENSE.TXT for details.
74ba319b5SDimitry Andric //
84ba319b5SDimitry Andric //===----------------------------------------------------------------------===//
94ba319b5SDimitry Andric // Fuzzer's main loop.
104ba319b5SDimitry Andric //===----------------------------------------------------------------------===//
114ba319b5SDimitry Andric 
124ba319b5SDimitry Andric #include "FuzzerCorpus.h"
134ba319b5SDimitry Andric #include "FuzzerIO.h"
144ba319b5SDimitry Andric #include "FuzzerInternal.h"
154ba319b5SDimitry Andric #include "FuzzerMutate.h"
164ba319b5SDimitry Andric #include "FuzzerRandom.h"
174ba319b5SDimitry Andric #include "FuzzerShmem.h"
184ba319b5SDimitry Andric #include "FuzzerTracePC.h"
194ba319b5SDimitry Andric #include <algorithm>
204ba319b5SDimitry Andric #include <cstring>
214ba319b5SDimitry Andric #include <memory>
224ba319b5SDimitry Andric #include <mutex>
234ba319b5SDimitry Andric #include <set>
244ba319b5SDimitry Andric 
254ba319b5SDimitry Andric #if defined(__has_include)
264ba319b5SDimitry Andric #if __has_include(<sanitizer / lsan_interface.h>)
274ba319b5SDimitry Andric #include <sanitizer/lsan_interface.h>
284ba319b5SDimitry Andric #endif
294ba319b5SDimitry Andric #endif
304ba319b5SDimitry Andric 
314ba319b5SDimitry Andric #define NO_SANITIZE_MEMORY
324ba319b5SDimitry Andric #if defined(__has_feature)
334ba319b5SDimitry Andric #if __has_feature(memory_sanitizer)
344ba319b5SDimitry Andric #undef NO_SANITIZE_MEMORY
354ba319b5SDimitry Andric #define NO_SANITIZE_MEMORY __attribute__((no_sanitize_memory))
364ba319b5SDimitry Andric #endif
374ba319b5SDimitry Andric #endif
384ba319b5SDimitry Andric 
394ba319b5SDimitry Andric namespace fuzzer {
404ba319b5SDimitry Andric static const size_t kMaxUnitSizeToPrint = 256;
414ba319b5SDimitry Andric 
424ba319b5SDimitry Andric thread_local bool Fuzzer::IsMyThread;
434ba319b5SDimitry Andric 
444ba319b5SDimitry Andric SharedMemoryRegion SMR;
454ba319b5SDimitry Andric 
464ba319b5SDimitry Andric bool RunningUserCallback = false;
474ba319b5SDimitry Andric 
484ba319b5SDimitry Andric // Only one Fuzzer per process.
494ba319b5SDimitry Andric static Fuzzer *F;
504ba319b5SDimitry Andric 
514ba319b5SDimitry Andric // Leak detection is expensive, so we first check if there were more mallocs
524ba319b5SDimitry Andric // than frees (using the sanitizer malloc hooks) and only then try to call lsan.
534ba319b5SDimitry Andric struct MallocFreeTracer {
Startfuzzer::MallocFreeTracer544ba319b5SDimitry Andric   void Start(int TraceLevel) {
554ba319b5SDimitry Andric     this->TraceLevel = TraceLevel;
564ba319b5SDimitry Andric     if (TraceLevel)
574ba319b5SDimitry Andric       Printf("MallocFreeTracer: START\n");
584ba319b5SDimitry Andric     Mallocs = 0;
594ba319b5SDimitry Andric     Frees = 0;
604ba319b5SDimitry Andric   }
614ba319b5SDimitry Andric   // Returns true if there were more mallocs than frees.
Stopfuzzer::MallocFreeTracer624ba319b5SDimitry Andric   bool Stop() {
634ba319b5SDimitry Andric     if (TraceLevel)
644ba319b5SDimitry Andric       Printf("MallocFreeTracer: STOP %zd %zd (%s)\n", Mallocs.load(),
654ba319b5SDimitry Andric              Frees.load(), Mallocs == Frees ? "same" : "DIFFERENT");
664ba319b5SDimitry Andric     bool Result = Mallocs > Frees;
674ba319b5SDimitry Andric     Mallocs = 0;
684ba319b5SDimitry Andric     Frees = 0;
694ba319b5SDimitry Andric     TraceLevel = 0;
704ba319b5SDimitry Andric     return Result;
714ba319b5SDimitry Andric   }
724ba319b5SDimitry Andric   std::atomic<size_t> Mallocs;
734ba319b5SDimitry Andric   std::atomic<size_t> Frees;
744ba319b5SDimitry Andric   int TraceLevel = 0;
754ba319b5SDimitry Andric 
764ba319b5SDimitry Andric   std::recursive_mutex TraceMutex;
774ba319b5SDimitry Andric   bool TraceDisabled = false;
784ba319b5SDimitry Andric };
794ba319b5SDimitry Andric 
804ba319b5SDimitry Andric static MallocFreeTracer AllocTracer;
814ba319b5SDimitry Andric 
824ba319b5SDimitry Andric // Locks printing and avoids nested hooks triggered from mallocs/frees in
834ba319b5SDimitry Andric // sanitizer.
844ba319b5SDimitry Andric class TraceLock {
854ba319b5SDimitry Andric public:
TraceLock()864ba319b5SDimitry Andric   TraceLock() : Lock(AllocTracer.TraceMutex) {
874ba319b5SDimitry Andric     AllocTracer.TraceDisabled = !AllocTracer.TraceDisabled;
884ba319b5SDimitry Andric   }
~TraceLock()894ba319b5SDimitry Andric   ~TraceLock() { AllocTracer.TraceDisabled = !AllocTracer.TraceDisabled; }
904ba319b5SDimitry Andric 
IsDisabled() const914ba319b5SDimitry Andric   bool IsDisabled() const {
924ba319b5SDimitry Andric     // This is already inverted value.
934ba319b5SDimitry Andric     return !AllocTracer.TraceDisabled;
944ba319b5SDimitry Andric   }
954ba319b5SDimitry Andric 
964ba319b5SDimitry Andric private:
974ba319b5SDimitry Andric   std::lock_guard<std::recursive_mutex> Lock;
984ba319b5SDimitry Andric };
994ba319b5SDimitry Andric 
1004ba319b5SDimitry Andric ATTRIBUTE_NO_SANITIZE_MEMORY
MallocHook(const volatile void * ptr,size_t size)1014ba319b5SDimitry Andric void MallocHook(const volatile void *ptr, size_t size) {
1024ba319b5SDimitry Andric   size_t N = AllocTracer.Mallocs++;
1034ba319b5SDimitry Andric   F->HandleMalloc(size);
1044ba319b5SDimitry Andric   if (int TraceLevel = AllocTracer.TraceLevel) {
1054ba319b5SDimitry Andric     TraceLock Lock;
1064ba319b5SDimitry Andric     if (Lock.IsDisabled())
1074ba319b5SDimitry Andric       return;
1084ba319b5SDimitry Andric     Printf("MALLOC[%zd] %p %zd\n", N, ptr, size);
1094ba319b5SDimitry Andric     if (TraceLevel >= 2 && EF)
1104ba319b5SDimitry Andric       PrintStackTrace();
1114ba319b5SDimitry Andric   }
1124ba319b5SDimitry Andric }
1134ba319b5SDimitry Andric 
1144ba319b5SDimitry Andric ATTRIBUTE_NO_SANITIZE_MEMORY
FreeHook(const volatile void * ptr)1154ba319b5SDimitry Andric void FreeHook(const volatile void *ptr) {
1164ba319b5SDimitry Andric   size_t N = AllocTracer.Frees++;
1174ba319b5SDimitry Andric   if (int TraceLevel = AllocTracer.TraceLevel) {
1184ba319b5SDimitry Andric     TraceLock Lock;
1194ba319b5SDimitry Andric     if (Lock.IsDisabled())
1204ba319b5SDimitry Andric       return;
1214ba319b5SDimitry Andric     Printf("FREE[%zd]   %p\n", N, ptr);
1224ba319b5SDimitry Andric     if (TraceLevel >= 2 && EF)
1234ba319b5SDimitry Andric       PrintStackTrace();
1244ba319b5SDimitry Andric   }
1254ba319b5SDimitry Andric }
1264ba319b5SDimitry Andric 
1274ba319b5SDimitry Andric // Crash on a single malloc that exceeds the rss limit.
HandleMalloc(size_t Size)1284ba319b5SDimitry Andric void Fuzzer::HandleMalloc(size_t Size) {
1294ba319b5SDimitry Andric   if (!Options.MallocLimitMb || (Size >> 20) < (size_t)Options.MallocLimitMb)
1304ba319b5SDimitry Andric     return;
1314ba319b5SDimitry Andric   Printf("==%d== ERROR: libFuzzer: out-of-memory (malloc(%zd))\n", GetPid(),
1324ba319b5SDimitry Andric          Size);
1334ba319b5SDimitry Andric   Printf("   To change the out-of-memory limit use -rss_limit_mb=<N>\n\n");
1344ba319b5SDimitry Andric   PrintStackTrace();
1354ba319b5SDimitry Andric   DumpCurrentUnit("oom-");
1364ba319b5SDimitry Andric   Printf("SUMMARY: libFuzzer: out-of-memory\n");
1374ba319b5SDimitry Andric   PrintFinalStats();
1384ba319b5SDimitry Andric   _Exit(Options.ErrorExitCode); // Stop right now.
1394ba319b5SDimitry Andric }
1404ba319b5SDimitry Andric 
Fuzzer(UserCallback CB,InputCorpus & Corpus,MutationDispatcher & MD,FuzzingOptions Options)1414ba319b5SDimitry Andric Fuzzer::Fuzzer(UserCallback CB, InputCorpus &Corpus, MutationDispatcher &MD,
1424ba319b5SDimitry Andric                FuzzingOptions Options)
1434ba319b5SDimitry Andric     : CB(CB), Corpus(Corpus), MD(MD), Options(Options) {
1444ba319b5SDimitry Andric   if (EF->__sanitizer_set_death_callback)
1454ba319b5SDimitry Andric     EF->__sanitizer_set_death_callback(StaticDeathCallback);
1464ba319b5SDimitry Andric   assert(!F);
1474ba319b5SDimitry Andric   F = this;
1484ba319b5SDimitry Andric   TPC.ResetMaps();
1494ba319b5SDimitry Andric   IsMyThread = true;
1504ba319b5SDimitry Andric   if (Options.DetectLeaks && EF->__sanitizer_install_malloc_and_free_hooks)
1514ba319b5SDimitry Andric     EF->__sanitizer_install_malloc_and_free_hooks(MallocHook, FreeHook);
1524ba319b5SDimitry Andric   TPC.SetUseCounters(Options.UseCounters);
1534ba319b5SDimitry Andric   TPC.SetUseValueProfileMask(Options.UseValueProfile);
1544ba319b5SDimitry Andric 
1554ba319b5SDimitry Andric   if (Options.Verbosity)
1564ba319b5SDimitry Andric     TPC.PrintModuleInfo();
1574ba319b5SDimitry Andric   if (!Options.OutputCorpus.empty() && Options.ReloadIntervalSec)
1584ba319b5SDimitry Andric     EpochOfLastReadOfOutputCorpus = GetEpoch(Options.OutputCorpus);
1594ba319b5SDimitry Andric   MaxInputLen = MaxMutationLen = Options.MaxLen;
1604ba319b5SDimitry Andric   TmpMaxMutationLen = Max(size_t(4), Corpus.MaxInputSize());
1614ba319b5SDimitry Andric   AllocateCurrentUnitData();
1624ba319b5SDimitry Andric   CurrentUnitSize = 0;
1634ba319b5SDimitry Andric   memset(BaseSha1, 0, sizeof(BaseSha1));
1644ba319b5SDimitry Andric   TPC.SetFocusFunction(Options.FocusFunction);
1654ba319b5SDimitry Andric   DFT.Init(Options.DataFlowTrace, Options.FocusFunction);
1664ba319b5SDimitry Andric }
1674ba319b5SDimitry Andric 
~Fuzzer()1684ba319b5SDimitry Andric Fuzzer::~Fuzzer() {}
1694ba319b5SDimitry Andric 
AllocateCurrentUnitData()1704ba319b5SDimitry Andric void Fuzzer::AllocateCurrentUnitData() {
1714ba319b5SDimitry Andric   if (CurrentUnitData || MaxInputLen == 0)
1724ba319b5SDimitry Andric     return;
1734ba319b5SDimitry Andric   CurrentUnitData = new uint8_t[MaxInputLen];
1744ba319b5SDimitry Andric }
1754ba319b5SDimitry Andric 
StaticDeathCallback()1764ba319b5SDimitry Andric void Fuzzer::StaticDeathCallback() {
1774ba319b5SDimitry Andric   assert(F);
1784ba319b5SDimitry Andric   F->DeathCallback();
1794ba319b5SDimitry Andric }
1804ba319b5SDimitry Andric 
DumpCurrentUnit(const char * Prefix)1814ba319b5SDimitry Andric void Fuzzer::DumpCurrentUnit(const char *Prefix) {
1824ba319b5SDimitry Andric   if (!CurrentUnitData)
1834ba319b5SDimitry Andric     return; // Happens when running individual inputs.
1844ba319b5SDimitry Andric   ScopedDisableMsanInterceptorChecks S;
1854ba319b5SDimitry Andric   MD.PrintMutationSequence();
1864ba319b5SDimitry Andric   Printf("; base unit: %s\n", Sha1ToString(BaseSha1).c_str());
1874ba319b5SDimitry Andric   size_t UnitSize = CurrentUnitSize;
1884ba319b5SDimitry Andric   if (UnitSize <= kMaxUnitSizeToPrint) {
1894ba319b5SDimitry Andric     PrintHexArray(CurrentUnitData, UnitSize, "\n");
1904ba319b5SDimitry Andric     PrintASCII(CurrentUnitData, UnitSize, "\n");
1914ba319b5SDimitry Andric   }
1924ba319b5SDimitry Andric   WriteUnitToFileWithPrefix({CurrentUnitData, CurrentUnitData + UnitSize},
1934ba319b5SDimitry Andric                             Prefix);
1944ba319b5SDimitry Andric }
1954ba319b5SDimitry Andric 
1964ba319b5SDimitry Andric NO_SANITIZE_MEMORY
DeathCallback()1974ba319b5SDimitry Andric void Fuzzer::DeathCallback() {
1984ba319b5SDimitry Andric   DumpCurrentUnit("crash-");
1994ba319b5SDimitry Andric   PrintFinalStats();
2004ba319b5SDimitry Andric }
2014ba319b5SDimitry Andric 
StaticAlarmCallback()2024ba319b5SDimitry Andric void Fuzzer::StaticAlarmCallback() {
2034ba319b5SDimitry Andric   assert(F);
2044ba319b5SDimitry Andric   F->AlarmCallback();
2054ba319b5SDimitry Andric }
2064ba319b5SDimitry Andric 
StaticCrashSignalCallback()2074ba319b5SDimitry Andric void Fuzzer::StaticCrashSignalCallback() {
2084ba319b5SDimitry Andric   assert(F);
2094ba319b5SDimitry Andric   F->CrashCallback();
2104ba319b5SDimitry Andric }
2114ba319b5SDimitry Andric 
StaticExitCallback()2124ba319b5SDimitry Andric void Fuzzer::StaticExitCallback() {
2134ba319b5SDimitry Andric   assert(F);
2144ba319b5SDimitry Andric   F->ExitCallback();
2154ba319b5SDimitry Andric }
2164ba319b5SDimitry Andric 
StaticInterruptCallback()2174ba319b5SDimitry Andric void Fuzzer::StaticInterruptCallback() {
2184ba319b5SDimitry Andric   assert(F);
2194ba319b5SDimitry Andric   F->InterruptCallback();
2204ba319b5SDimitry Andric }
2214ba319b5SDimitry Andric 
StaticGracefulExitCallback()2224ba319b5SDimitry Andric void Fuzzer::StaticGracefulExitCallback() {
2234ba319b5SDimitry Andric   assert(F);
2244ba319b5SDimitry Andric   F->GracefulExitRequested = true;
2254ba319b5SDimitry Andric   Printf("INFO: signal received, trying to exit gracefully\n");
2264ba319b5SDimitry Andric }
2274ba319b5SDimitry Andric 
StaticFileSizeExceedCallback()2284ba319b5SDimitry Andric void Fuzzer::StaticFileSizeExceedCallback() {
2294ba319b5SDimitry Andric   Printf("==%lu== ERROR: libFuzzer: file size exceeded\n", GetPid());
2304ba319b5SDimitry Andric   exit(1);
2314ba319b5SDimitry Andric }
2324ba319b5SDimitry Andric 
CrashCallback()2334ba319b5SDimitry Andric void Fuzzer::CrashCallback() {
2344ba319b5SDimitry Andric   if (EF->__sanitizer_acquire_crash_state)
2354ba319b5SDimitry Andric     EF->__sanitizer_acquire_crash_state();
2364ba319b5SDimitry Andric   Printf("==%lu== ERROR: libFuzzer: deadly signal\n", GetPid());
2374ba319b5SDimitry Andric   PrintStackTrace();
2384ba319b5SDimitry Andric   Printf("NOTE: libFuzzer has rudimentary signal handlers.\n"
2394ba319b5SDimitry Andric          "      Combine libFuzzer with AddressSanitizer or similar for better "
2404ba319b5SDimitry Andric          "crash reports.\n");
2414ba319b5SDimitry Andric   Printf("SUMMARY: libFuzzer: deadly signal\n");
2424ba319b5SDimitry Andric   DumpCurrentUnit("crash-");
2434ba319b5SDimitry Andric   PrintFinalStats();
2444ba319b5SDimitry Andric   _Exit(Options.ErrorExitCode); // Stop right now.
2454ba319b5SDimitry Andric }
2464ba319b5SDimitry Andric 
ExitCallback()2474ba319b5SDimitry Andric void Fuzzer::ExitCallback() {
2484ba319b5SDimitry Andric   if (!RunningUserCallback)
2494ba319b5SDimitry Andric     return; // This exit did not come from the user callback
2504ba319b5SDimitry Andric   if (EF->__sanitizer_acquire_crash_state &&
2514ba319b5SDimitry Andric       !EF->__sanitizer_acquire_crash_state())
2524ba319b5SDimitry Andric     return;
2534ba319b5SDimitry Andric   Printf("==%lu== ERROR: libFuzzer: fuzz target exited\n", GetPid());
2544ba319b5SDimitry Andric   PrintStackTrace();
2554ba319b5SDimitry Andric   Printf("SUMMARY: libFuzzer: fuzz target exited\n");
2564ba319b5SDimitry Andric   DumpCurrentUnit("crash-");
2574ba319b5SDimitry Andric   PrintFinalStats();
2584ba319b5SDimitry Andric   _Exit(Options.ErrorExitCode);
2594ba319b5SDimitry Andric }
2604ba319b5SDimitry Andric 
MaybeExitGracefully()2614ba319b5SDimitry Andric void Fuzzer::MaybeExitGracefully() {
2624ba319b5SDimitry Andric   if (!GracefulExitRequested) return;
2634ba319b5SDimitry Andric   Printf("==%lu== INFO: libFuzzer: exiting as requested\n", GetPid());
2644ba319b5SDimitry Andric   PrintFinalStats();
2654ba319b5SDimitry Andric   _Exit(0);
2664ba319b5SDimitry Andric }
2674ba319b5SDimitry Andric 
InterruptCallback()2684ba319b5SDimitry Andric void Fuzzer::InterruptCallback() {
2694ba319b5SDimitry Andric   Printf("==%lu== libFuzzer: run interrupted; exiting\n", GetPid());
2704ba319b5SDimitry Andric   PrintFinalStats();
2714ba319b5SDimitry Andric   _Exit(0); // Stop right now, don't perform any at-exit actions.
2724ba319b5SDimitry Andric }
2734ba319b5SDimitry Andric 
2744ba319b5SDimitry Andric NO_SANITIZE_MEMORY
AlarmCallback()2754ba319b5SDimitry Andric void Fuzzer::AlarmCallback() {
2764ba319b5SDimitry Andric   assert(Options.UnitTimeoutSec > 0);
2774ba319b5SDimitry Andric   // In Windows Alarm callback is executed by a different thread.
278*b5893f02SDimitry Andric   // NetBSD's current behavior needs this change too.
279*b5893f02SDimitry Andric #if !LIBFUZZER_WINDOWS && !LIBFUZZER_NETBSD
2804ba319b5SDimitry Andric   if (!InFuzzingThread())
2814ba319b5SDimitry Andric     return;
2824ba319b5SDimitry Andric #endif
2834ba319b5SDimitry Andric   if (!RunningUserCallback)
2844ba319b5SDimitry Andric     return; // We have not started running units yet.
2854ba319b5SDimitry Andric   size_t Seconds =
2864ba319b5SDimitry Andric       duration_cast<seconds>(system_clock::now() - UnitStartTime).count();
2874ba319b5SDimitry Andric   if (Seconds == 0)
2884ba319b5SDimitry Andric     return;
2894ba319b5SDimitry Andric   if (Options.Verbosity >= 2)
2904ba319b5SDimitry Andric     Printf("AlarmCallback %zd\n", Seconds);
2914ba319b5SDimitry Andric   if (Seconds >= (size_t)Options.UnitTimeoutSec) {
2924ba319b5SDimitry Andric     if (EF->__sanitizer_acquire_crash_state &&
2934ba319b5SDimitry Andric         !EF->__sanitizer_acquire_crash_state())
2944ba319b5SDimitry Andric       return;
2954ba319b5SDimitry Andric     Printf("ALARM: working on the last Unit for %zd seconds\n", Seconds);
2964ba319b5SDimitry Andric     Printf("       and the timeout value is %d (use -timeout=N to change)\n",
2974ba319b5SDimitry Andric            Options.UnitTimeoutSec);
2984ba319b5SDimitry Andric     DumpCurrentUnit("timeout-");
2994ba319b5SDimitry Andric     Printf("==%lu== ERROR: libFuzzer: timeout after %d seconds\n", GetPid(),
3004ba319b5SDimitry Andric            Seconds);
3014ba319b5SDimitry Andric     PrintStackTrace();
3024ba319b5SDimitry Andric     Printf("SUMMARY: libFuzzer: timeout\n");
3034ba319b5SDimitry Andric     PrintFinalStats();
3044ba319b5SDimitry Andric     _Exit(Options.TimeoutExitCode); // Stop right now.
3054ba319b5SDimitry Andric   }
3064ba319b5SDimitry Andric }
3074ba319b5SDimitry Andric 
RssLimitCallback()3084ba319b5SDimitry Andric void Fuzzer::RssLimitCallback() {
3094ba319b5SDimitry Andric   if (EF->__sanitizer_acquire_crash_state &&
3104ba319b5SDimitry Andric       !EF->__sanitizer_acquire_crash_state())
3114ba319b5SDimitry Andric     return;
3124ba319b5SDimitry Andric   Printf(
3134ba319b5SDimitry Andric       "==%lu== ERROR: libFuzzer: out-of-memory (used: %zdMb; limit: %zdMb)\n",
3144ba319b5SDimitry Andric       GetPid(), GetPeakRSSMb(), Options.RssLimitMb);
3154ba319b5SDimitry Andric   Printf("   To change the out-of-memory limit use -rss_limit_mb=<N>\n\n");
3164ba319b5SDimitry Andric   PrintMemoryProfile();
3174ba319b5SDimitry Andric   DumpCurrentUnit("oom-");
3184ba319b5SDimitry Andric   Printf("SUMMARY: libFuzzer: out-of-memory\n");
3194ba319b5SDimitry Andric   PrintFinalStats();
3204ba319b5SDimitry Andric   _Exit(Options.ErrorExitCode); // Stop right now.
3214ba319b5SDimitry Andric }
3224ba319b5SDimitry Andric 
PrintStats(const char * Where,const char * End,size_t Units)3234ba319b5SDimitry Andric void Fuzzer::PrintStats(const char *Where, const char *End, size_t Units) {
3244ba319b5SDimitry Andric   size_t ExecPerSec = execPerSec();
3254ba319b5SDimitry Andric   if (!Options.Verbosity)
3264ba319b5SDimitry Andric     return;
3274ba319b5SDimitry Andric   Printf("#%zd\t%s", TotalNumberOfRuns, Where);
3284ba319b5SDimitry Andric   if (size_t N = TPC.GetTotalPCCoverage())
3294ba319b5SDimitry Andric     Printf(" cov: %zd", N);
3304ba319b5SDimitry Andric   if (size_t N = Corpus.NumFeatures())
3314ba319b5SDimitry Andric     Printf(" ft: %zd", N);
3324ba319b5SDimitry Andric   if (!Corpus.empty()) {
3334ba319b5SDimitry Andric     Printf(" corp: %zd", Corpus.NumActiveUnits());
3344ba319b5SDimitry Andric     if (size_t N = Corpus.SizeInBytes()) {
3354ba319b5SDimitry Andric       if (N < (1 << 14))
3364ba319b5SDimitry Andric         Printf("/%zdb", N);
3374ba319b5SDimitry Andric       else if (N < (1 << 24))
3384ba319b5SDimitry Andric         Printf("/%zdKb", N >> 10);
3394ba319b5SDimitry Andric       else
3404ba319b5SDimitry Andric         Printf("/%zdMb", N >> 20);
3414ba319b5SDimitry Andric     }
3424ba319b5SDimitry Andric     if (size_t FF = Corpus.NumInputsThatTouchFocusFunction())
3434ba319b5SDimitry Andric       Printf(" focus: %zd", FF);
3444ba319b5SDimitry Andric   }
3454ba319b5SDimitry Andric   if (TmpMaxMutationLen)
3464ba319b5SDimitry Andric     Printf(" lim: %zd", TmpMaxMutationLen);
3474ba319b5SDimitry Andric   if (Units)
3484ba319b5SDimitry Andric     Printf(" units: %zd", Units);
3494ba319b5SDimitry Andric 
3504ba319b5SDimitry Andric   Printf(" exec/s: %zd", ExecPerSec);
3514ba319b5SDimitry Andric   Printf(" rss: %zdMb", GetPeakRSSMb());
3524ba319b5SDimitry Andric   Printf("%s", End);
3534ba319b5SDimitry Andric }
3544ba319b5SDimitry Andric 
PrintFinalStats()3554ba319b5SDimitry Andric void Fuzzer::PrintFinalStats() {
3564ba319b5SDimitry Andric   if (Options.PrintCoverage)
3574ba319b5SDimitry Andric     TPC.PrintCoverage();
3584ba319b5SDimitry Andric   if (Options.DumpCoverage)
3594ba319b5SDimitry Andric     TPC.DumpCoverage();
3604ba319b5SDimitry Andric   if (Options.PrintCorpusStats)
3614ba319b5SDimitry Andric     Corpus.PrintStats();
3624ba319b5SDimitry Andric   if (!Options.PrintFinalStats)
3634ba319b5SDimitry Andric     return;
3644ba319b5SDimitry Andric   size_t ExecPerSec = execPerSec();
3654ba319b5SDimitry Andric   Printf("stat::number_of_executed_units: %zd\n", TotalNumberOfRuns);
3664ba319b5SDimitry Andric   Printf("stat::average_exec_per_sec:     %zd\n", ExecPerSec);
3674ba319b5SDimitry Andric   Printf("stat::new_units_added:          %zd\n", NumberOfNewUnitsAdded);
3684ba319b5SDimitry Andric   Printf("stat::slowest_unit_time_sec:    %zd\n", TimeOfLongestUnitInSeconds);
3694ba319b5SDimitry Andric   Printf("stat::peak_rss_mb:              %zd\n", GetPeakRSSMb());
3704ba319b5SDimitry Andric }
3714ba319b5SDimitry Andric 
SetMaxInputLen(size_t MaxInputLen)3724ba319b5SDimitry Andric void Fuzzer::SetMaxInputLen(size_t MaxInputLen) {
3734ba319b5SDimitry Andric   assert(this->MaxInputLen == 0); // Can only reset MaxInputLen from 0 to non-0.
3744ba319b5SDimitry Andric   assert(MaxInputLen);
3754ba319b5SDimitry Andric   this->MaxInputLen = MaxInputLen;
3764ba319b5SDimitry Andric   this->MaxMutationLen = MaxInputLen;
3774ba319b5SDimitry Andric   AllocateCurrentUnitData();
3784ba319b5SDimitry Andric   Printf("INFO: -max_len is not provided; "
3794ba319b5SDimitry Andric          "libFuzzer will not generate inputs larger than %zd bytes\n",
3804ba319b5SDimitry Andric          MaxInputLen);
3814ba319b5SDimitry Andric }
3824ba319b5SDimitry Andric 
SetMaxMutationLen(size_t MaxMutationLen)3834ba319b5SDimitry Andric void Fuzzer::SetMaxMutationLen(size_t MaxMutationLen) {
3844ba319b5SDimitry Andric   assert(MaxMutationLen && MaxMutationLen <= MaxInputLen);
3854ba319b5SDimitry Andric   this->MaxMutationLen = MaxMutationLen;
3864ba319b5SDimitry Andric }
3874ba319b5SDimitry Andric 
CheckExitOnSrcPosOrItem()3884ba319b5SDimitry Andric void Fuzzer::CheckExitOnSrcPosOrItem() {
3894ba319b5SDimitry Andric   if (!Options.ExitOnSrcPos.empty()) {
3904ba319b5SDimitry Andric     static auto *PCsSet = new Set<uintptr_t>;
3914ba319b5SDimitry Andric     auto HandlePC = [&](uintptr_t PC) {
3924ba319b5SDimitry Andric       if (!PCsSet->insert(PC).second)
3934ba319b5SDimitry Andric         return;
3944ba319b5SDimitry Andric       std::string Descr = DescribePC("%F %L", PC + 1);
3954ba319b5SDimitry Andric       if (Descr.find(Options.ExitOnSrcPos) != std::string::npos) {
3964ba319b5SDimitry Andric         Printf("INFO: found line matching '%s', exiting.\n",
3974ba319b5SDimitry Andric                Options.ExitOnSrcPos.c_str());
3984ba319b5SDimitry Andric         _Exit(0);
3994ba319b5SDimitry Andric       }
4004ba319b5SDimitry Andric     };
4014ba319b5SDimitry Andric     TPC.ForEachObservedPC(HandlePC);
4024ba319b5SDimitry Andric   }
4034ba319b5SDimitry Andric   if (!Options.ExitOnItem.empty()) {
4044ba319b5SDimitry Andric     if (Corpus.HasUnit(Options.ExitOnItem)) {
4054ba319b5SDimitry Andric       Printf("INFO: found item with checksum '%s', exiting.\n",
4064ba319b5SDimitry Andric              Options.ExitOnItem.c_str());
4074ba319b5SDimitry Andric       _Exit(0);
4084ba319b5SDimitry Andric     }
4094ba319b5SDimitry Andric   }
4104ba319b5SDimitry Andric }
4114ba319b5SDimitry Andric 
RereadOutputCorpus(size_t MaxSize)4124ba319b5SDimitry Andric void Fuzzer::RereadOutputCorpus(size_t MaxSize) {
4134ba319b5SDimitry Andric   if (Options.OutputCorpus.empty() || !Options.ReloadIntervalSec)
4144ba319b5SDimitry Andric     return;
4154ba319b5SDimitry Andric   Vector<Unit> AdditionalCorpus;
4164ba319b5SDimitry Andric   ReadDirToVectorOfUnits(Options.OutputCorpus.c_str(), &AdditionalCorpus,
4174ba319b5SDimitry Andric                          &EpochOfLastReadOfOutputCorpus, MaxSize,
4184ba319b5SDimitry Andric                          /*ExitOnError*/ false);
4194ba319b5SDimitry Andric   if (Options.Verbosity >= 2)
4204ba319b5SDimitry Andric     Printf("Reload: read %zd new units.\n", AdditionalCorpus.size());
4214ba319b5SDimitry Andric   bool Reloaded = false;
4224ba319b5SDimitry Andric   for (auto &U : AdditionalCorpus) {
4234ba319b5SDimitry Andric     if (U.size() > MaxSize)
4244ba319b5SDimitry Andric       U.resize(MaxSize);
4254ba319b5SDimitry Andric     if (!Corpus.HasUnit(U)) {
4264ba319b5SDimitry Andric       if (RunOne(U.data(), U.size())) {
4274ba319b5SDimitry Andric         CheckExitOnSrcPosOrItem();
4284ba319b5SDimitry Andric         Reloaded = true;
4294ba319b5SDimitry Andric       }
4304ba319b5SDimitry Andric     }
4314ba319b5SDimitry Andric   }
4324ba319b5SDimitry Andric   if (Reloaded)
4334ba319b5SDimitry Andric     PrintStats("RELOAD");
4344ba319b5SDimitry Andric }
4354ba319b5SDimitry Andric 
PrintPulseAndReportSlowInput(const uint8_t * Data,size_t Size)4364ba319b5SDimitry Andric void Fuzzer::PrintPulseAndReportSlowInput(const uint8_t *Data, size_t Size) {
4374ba319b5SDimitry Andric   auto TimeOfUnit =
4384ba319b5SDimitry Andric       duration_cast<seconds>(UnitStopTime - UnitStartTime).count();
4394ba319b5SDimitry Andric   if (!(TotalNumberOfRuns & (TotalNumberOfRuns - 1)) &&
4404ba319b5SDimitry Andric       secondsSinceProcessStartUp() >= 2)
4414ba319b5SDimitry Andric     PrintStats("pulse ");
4424ba319b5SDimitry Andric   if (TimeOfUnit > TimeOfLongestUnitInSeconds * 1.1 &&
4434ba319b5SDimitry Andric       TimeOfUnit >= Options.ReportSlowUnits) {
4444ba319b5SDimitry Andric     TimeOfLongestUnitInSeconds = TimeOfUnit;
4454ba319b5SDimitry Andric     Printf("Slowest unit: %zd s:\n", TimeOfLongestUnitInSeconds);
4464ba319b5SDimitry Andric     WriteUnitToFileWithPrefix({Data, Data + Size}, "slow-unit-");
4474ba319b5SDimitry Andric   }
4484ba319b5SDimitry Andric }
4494ba319b5SDimitry Andric 
RunOne(const uint8_t * Data,size_t Size,bool MayDeleteFile,InputInfo * II,bool * FoundUniqFeatures)4504ba319b5SDimitry Andric bool Fuzzer::RunOne(const uint8_t *Data, size_t Size, bool MayDeleteFile,
4514ba319b5SDimitry Andric                     InputInfo *II, bool *FoundUniqFeatures) {
4524ba319b5SDimitry Andric   if (!Size)
4534ba319b5SDimitry Andric     return false;
4544ba319b5SDimitry Andric 
4554ba319b5SDimitry Andric   ExecuteCallback(Data, Size);
4564ba319b5SDimitry Andric 
4574ba319b5SDimitry Andric   UniqFeatureSetTmp.clear();
4584ba319b5SDimitry Andric   size_t FoundUniqFeaturesOfII = 0;
4594ba319b5SDimitry Andric   size_t NumUpdatesBefore = Corpus.NumFeatureUpdates();
4604ba319b5SDimitry Andric   TPC.CollectFeatures([&](size_t Feature) {
4614ba319b5SDimitry Andric     if (Corpus.AddFeature(Feature, Size, Options.Shrink))
4624ba319b5SDimitry Andric       UniqFeatureSetTmp.push_back(Feature);
4634ba319b5SDimitry Andric     if (Options.ReduceInputs && II)
4644ba319b5SDimitry Andric       if (std::binary_search(II->UniqFeatureSet.begin(),
4654ba319b5SDimitry Andric                              II->UniqFeatureSet.end(), Feature))
4664ba319b5SDimitry Andric         FoundUniqFeaturesOfII++;
4674ba319b5SDimitry Andric   });
4684ba319b5SDimitry Andric   if (FoundUniqFeatures)
4694ba319b5SDimitry Andric     *FoundUniqFeatures = FoundUniqFeaturesOfII;
4704ba319b5SDimitry Andric   PrintPulseAndReportSlowInput(Data, Size);
4714ba319b5SDimitry Andric   size_t NumNewFeatures = Corpus.NumFeatureUpdates() - NumUpdatesBefore;
4724ba319b5SDimitry Andric   if (NumNewFeatures) {
4734ba319b5SDimitry Andric     TPC.UpdateObservedPCs();
4744ba319b5SDimitry Andric     Corpus.AddToCorpus({Data, Data + Size}, NumNewFeatures, MayDeleteFile,
4754ba319b5SDimitry Andric                        TPC.ObservedFocusFunction(), UniqFeatureSetTmp, DFT, II);
4764ba319b5SDimitry Andric     return true;
4774ba319b5SDimitry Andric   }
4784ba319b5SDimitry Andric   if (II && FoundUniqFeaturesOfII &&
4794ba319b5SDimitry Andric       II->DataFlowTraceForFocusFunction.empty() &&
4804ba319b5SDimitry Andric       FoundUniqFeaturesOfII == II->UniqFeatureSet.size() &&
4814ba319b5SDimitry Andric       II->U.size() > Size) {
4824ba319b5SDimitry Andric     Corpus.Replace(II, {Data, Data + Size});
4834ba319b5SDimitry Andric     return true;
4844ba319b5SDimitry Andric   }
4854ba319b5SDimitry Andric   return false;
4864ba319b5SDimitry Andric }
4874ba319b5SDimitry Andric 
GetCurrentUnitInFuzzingThead(const uint8_t ** Data) const4884ba319b5SDimitry Andric size_t Fuzzer::GetCurrentUnitInFuzzingThead(const uint8_t **Data) const {
4894ba319b5SDimitry Andric   assert(InFuzzingThread());
4904ba319b5SDimitry Andric   *Data = CurrentUnitData;
4914ba319b5SDimitry Andric   return CurrentUnitSize;
4924ba319b5SDimitry Andric }
4934ba319b5SDimitry Andric 
CrashOnOverwrittenData()4944ba319b5SDimitry Andric void Fuzzer::CrashOnOverwrittenData() {
4954ba319b5SDimitry Andric   Printf("==%d== ERROR: libFuzzer: fuzz target overwrites it's const input\n",
4964ba319b5SDimitry Andric          GetPid());
4974ba319b5SDimitry Andric   DumpCurrentUnit("crash-");
4984ba319b5SDimitry Andric   Printf("SUMMARY: libFuzzer: out-of-memory\n");
4994ba319b5SDimitry Andric   _Exit(Options.ErrorExitCode); // Stop right now.
5004ba319b5SDimitry Andric }
5014ba319b5SDimitry Andric 
5024ba319b5SDimitry Andric // Compare two arrays, but not all bytes if the arrays are large.
LooseMemeq(const uint8_t * A,const uint8_t * B,size_t Size)5034ba319b5SDimitry Andric static bool LooseMemeq(const uint8_t *A, const uint8_t *B, size_t Size) {
5044ba319b5SDimitry Andric   const size_t Limit = 64;
5054ba319b5SDimitry Andric   if (Size <= 64)
5064ba319b5SDimitry Andric     return !memcmp(A, B, Size);
5074ba319b5SDimitry Andric   // Compare first and last Limit/2 bytes.
5084ba319b5SDimitry Andric   return !memcmp(A, B, Limit / 2) &&
5094ba319b5SDimitry Andric          !memcmp(A + Size - Limit / 2, B + Size - Limit / 2, Limit / 2);
5104ba319b5SDimitry Andric }
5114ba319b5SDimitry Andric 
ExecuteCallback(const uint8_t * Data,size_t Size)5124ba319b5SDimitry Andric void Fuzzer::ExecuteCallback(const uint8_t *Data, size_t Size) {
5134ba319b5SDimitry Andric   TPC.RecordInitialStack();
5144ba319b5SDimitry Andric   TotalNumberOfRuns++;
5154ba319b5SDimitry Andric   assert(InFuzzingThread());
5164ba319b5SDimitry Andric   if (SMR.IsClient())
5174ba319b5SDimitry Andric     SMR.WriteByteArray(Data, Size);
5184ba319b5SDimitry Andric   // We copy the contents of Unit into a separate heap buffer
5194ba319b5SDimitry Andric   // so that we reliably find buffer overflows in it.
5204ba319b5SDimitry Andric   uint8_t *DataCopy = new uint8_t[Size];
5214ba319b5SDimitry Andric   memcpy(DataCopy, Data, Size);
5224ba319b5SDimitry Andric   if (EF->__msan_unpoison)
5234ba319b5SDimitry Andric     EF->__msan_unpoison(DataCopy, Size);
5244ba319b5SDimitry Andric   if (CurrentUnitData && CurrentUnitData != Data)
5254ba319b5SDimitry Andric     memcpy(CurrentUnitData, Data, Size);
5264ba319b5SDimitry Andric   CurrentUnitSize = Size;
5274ba319b5SDimitry Andric   {
5284ba319b5SDimitry Andric     ScopedEnableMsanInterceptorChecks S;
5294ba319b5SDimitry Andric     AllocTracer.Start(Options.TraceMalloc);
5304ba319b5SDimitry Andric     UnitStartTime = system_clock::now();
5314ba319b5SDimitry Andric     TPC.ResetMaps();
5324ba319b5SDimitry Andric     RunningUserCallback = true;
5334ba319b5SDimitry Andric     int Res = CB(DataCopy, Size);
5344ba319b5SDimitry Andric     RunningUserCallback = false;
5354ba319b5SDimitry Andric     UnitStopTime = system_clock::now();
5364ba319b5SDimitry Andric     (void)Res;
5374ba319b5SDimitry Andric     assert(Res == 0);
5384ba319b5SDimitry Andric     HasMoreMallocsThanFrees = AllocTracer.Stop();
5394ba319b5SDimitry Andric   }
5404ba319b5SDimitry Andric   if (!LooseMemeq(DataCopy, Data, Size))
5414ba319b5SDimitry Andric     CrashOnOverwrittenData();
5424ba319b5SDimitry Andric   CurrentUnitSize = 0;
5434ba319b5SDimitry Andric   delete[] DataCopy;
5444ba319b5SDimitry Andric }
5454ba319b5SDimitry Andric 
WriteToOutputCorpus(const Unit & U)5464ba319b5SDimitry Andric void Fuzzer::WriteToOutputCorpus(const Unit &U) {
5474ba319b5SDimitry Andric   if (Options.OnlyASCII)
5484ba319b5SDimitry Andric     assert(IsASCII(U));
5494ba319b5SDimitry Andric   if (Options.OutputCorpus.empty())
5504ba319b5SDimitry Andric     return;
5514ba319b5SDimitry Andric   std::string Path = DirPlusFile(Options.OutputCorpus, Hash(U));
5524ba319b5SDimitry Andric   WriteToFile(U, Path);
5534ba319b5SDimitry Andric   if (Options.Verbosity >= 2)
5544ba319b5SDimitry Andric     Printf("Written %zd bytes to %s\n", U.size(), Path.c_str());
5554ba319b5SDimitry Andric }
5564ba319b5SDimitry Andric 
WriteUnitToFileWithPrefix(const Unit & U,const char * Prefix)5574ba319b5SDimitry Andric void Fuzzer::WriteUnitToFileWithPrefix(const Unit &U, const char *Prefix) {
5584ba319b5SDimitry Andric   if (!Options.SaveArtifacts)
5594ba319b5SDimitry Andric     return;
5604ba319b5SDimitry Andric   std::string Path = Options.ArtifactPrefix + Prefix + Hash(U);
5614ba319b5SDimitry Andric   if (!Options.ExactArtifactPath.empty())
5624ba319b5SDimitry Andric     Path = Options.ExactArtifactPath; // Overrides ArtifactPrefix.
5634ba319b5SDimitry Andric   WriteToFile(U, Path);
5644ba319b5SDimitry Andric   Printf("artifact_prefix='%s'; Test unit written to %s\n",
5654ba319b5SDimitry Andric          Options.ArtifactPrefix.c_str(), Path.c_str());
5664ba319b5SDimitry Andric   if (U.size() <= kMaxUnitSizeToPrint)
5674ba319b5SDimitry Andric     Printf("Base64: %s\n", Base64(U).c_str());
5684ba319b5SDimitry Andric }
5694ba319b5SDimitry Andric 
PrintStatusForNewUnit(const Unit & U,const char * Text)5704ba319b5SDimitry Andric void Fuzzer::PrintStatusForNewUnit(const Unit &U, const char *Text) {
5714ba319b5SDimitry Andric   if (!Options.PrintNEW)
5724ba319b5SDimitry Andric     return;
5734ba319b5SDimitry Andric   PrintStats(Text, "");
5744ba319b5SDimitry Andric   if (Options.Verbosity) {
5754ba319b5SDimitry Andric     Printf(" L: %zd/%zd ", U.size(), Corpus.MaxInputSize());
5764ba319b5SDimitry Andric     MD.PrintMutationSequence();
5774ba319b5SDimitry Andric     Printf("\n");
5784ba319b5SDimitry Andric   }
5794ba319b5SDimitry Andric }
5804ba319b5SDimitry Andric 
ReportNewCoverage(InputInfo * II,const Unit & U)5814ba319b5SDimitry Andric void Fuzzer::ReportNewCoverage(InputInfo *II, const Unit &U) {
5824ba319b5SDimitry Andric   II->NumSuccessfullMutations++;
5834ba319b5SDimitry Andric   MD.RecordSuccessfulMutationSequence();
5844ba319b5SDimitry Andric   PrintStatusForNewUnit(U, II->Reduced ? "REDUCE" : "NEW   ");
5854ba319b5SDimitry Andric   WriteToOutputCorpus(U);
5864ba319b5SDimitry Andric   NumberOfNewUnitsAdded++;
5874ba319b5SDimitry Andric   CheckExitOnSrcPosOrItem(); // Check only after the unit is saved to corpus.
5884ba319b5SDimitry Andric   LastCorpusUpdateRun = TotalNumberOfRuns;
5894ba319b5SDimitry Andric }
5904ba319b5SDimitry Andric 
5914ba319b5SDimitry Andric // Tries detecting a memory leak on the particular input that we have just
5924ba319b5SDimitry Andric // executed before calling this function.
TryDetectingAMemoryLeak(const uint8_t * Data,size_t Size,bool DuringInitialCorpusExecution)5934ba319b5SDimitry Andric void Fuzzer::TryDetectingAMemoryLeak(const uint8_t *Data, size_t Size,
5944ba319b5SDimitry Andric                                      bool DuringInitialCorpusExecution) {
5954ba319b5SDimitry Andric   if (!HasMoreMallocsThanFrees)
5964ba319b5SDimitry Andric     return; // mallocs==frees, a leak is unlikely.
5974ba319b5SDimitry Andric   if (!Options.DetectLeaks)
5984ba319b5SDimitry Andric     return;
5994ba319b5SDimitry Andric   if (!DuringInitialCorpusExecution &&
6004ba319b5SDimitry Andric       TotalNumberOfRuns >= Options.MaxNumberOfRuns)
6014ba319b5SDimitry Andric     return;
6024ba319b5SDimitry Andric   if (!&(EF->__lsan_enable) || !&(EF->__lsan_disable) ||
6034ba319b5SDimitry Andric       !(EF->__lsan_do_recoverable_leak_check))
6044ba319b5SDimitry Andric     return; // No lsan.
6054ba319b5SDimitry Andric   // Run the target once again, but with lsan disabled so that if there is
6064ba319b5SDimitry Andric   // a real leak we do not report it twice.
6074ba319b5SDimitry Andric   EF->__lsan_disable();
6084ba319b5SDimitry Andric   ExecuteCallback(Data, Size);
6094ba319b5SDimitry Andric   EF->__lsan_enable();
6104ba319b5SDimitry Andric   if (!HasMoreMallocsThanFrees)
6114ba319b5SDimitry Andric     return; // a leak is unlikely.
6124ba319b5SDimitry Andric   if (NumberOfLeakDetectionAttempts++ > 1000) {
6134ba319b5SDimitry Andric     Options.DetectLeaks = false;
6144ba319b5SDimitry Andric     Printf("INFO: libFuzzer disabled leak detection after every mutation.\n"
6154ba319b5SDimitry Andric            "      Most likely the target function accumulates allocated\n"
6164ba319b5SDimitry Andric            "      memory in a global state w/o actually leaking it.\n"
6174ba319b5SDimitry Andric            "      You may try running this binary with -trace_malloc=[12]"
6184ba319b5SDimitry Andric            "      to get a trace of mallocs and frees.\n"
6194ba319b5SDimitry Andric            "      If LeakSanitizer is enabled in this process it will still\n"
6204ba319b5SDimitry Andric            "      run on the process shutdown.\n");
6214ba319b5SDimitry Andric     return;
6224ba319b5SDimitry Andric   }
6234ba319b5SDimitry Andric   // Now perform the actual lsan pass. This is expensive and we must ensure
6244ba319b5SDimitry Andric   // we don't call it too often.
6254ba319b5SDimitry Andric   if (EF->__lsan_do_recoverable_leak_check()) { // Leak is found, report it.
6264ba319b5SDimitry Andric     if (DuringInitialCorpusExecution)
6274ba319b5SDimitry Andric       Printf("\nINFO: a leak has been found in the initial corpus.\n\n");
6284ba319b5SDimitry Andric     Printf("INFO: to ignore leaks on libFuzzer side use -detect_leaks=0.\n\n");
6294ba319b5SDimitry Andric     CurrentUnitSize = Size;
6304ba319b5SDimitry Andric     DumpCurrentUnit("leak-");
6314ba319b5SDimitry Andric     PrintFinalStats();
6324ba319b5SDimitry Andric     _Exit(Options.ErrorExitCode); // not exit() to disable lsan further on.
6334ba319b5SDimitry Andric   }
6344ba319b5SDimitry Andric }
6354ba319b5SDimitry Andric 
MutateAndTestOne()6364ba319b5SDimitry Andric void Fuzzer::MutateAndTestOne() {
6374ba319b5SDimitry Andric   MD.StartMutationSequence();
6384ba319b5SDimitry Andric 
6394ba319b5SDimitry Andric   auto &II = Corpus.ChooseUnitToMutate(MD.GetRand());
6404ba319b5SDimitry Andric   const auto &U = II.U;
6414ba319b5SDimitry Andric   memcpy(BaseSha1, II.Sha1, sizeof(BaseSha1));
6424ba319b5SDimitry Andric   assert(CurrentUnitData);
6434ba319b5SDimitry Andric   size_t Size = U.size();
6444ba319b5SDimitry Andric   assert(Size <= MaxInputLen && "Oversized Unit");
6454ba319b5SDimitry Andric   memcpy(CurrentUnitData, U.data(), Size);
6464ba319b5SDimitry Andric 
6474ba319b5SDimitry Andric   assert(MaxMutationLen > 0);
6484ba319b5SDimitry Andric 
6494ba319b5SDimitry Andric   size_t CurrentMaxMutationLen =
6504ba319b5SDimitry Andric       Min(MaxMutationLen, Max(U.size(), TmpMaxMutationLen));
6514ba319b5SDimitry Andric   assert(CurrentMaxMutationLen > 0);
6524ba319b5SDimitry Andric 
6534ba319b5SDimitry Andric   for (int i = 0; i < Options.MutateDepth; i++) {
6544ba319b5SDimitry Andric     if (TotalNumberOfRuns >= Options.MaxNumberOfRuns)
6554ba319b5SDimitry Andric       break;
6564ba319b5SDimitry Andric     MaybeExitGracefully();
6574ba319b5SDimitry Andric     size_t NewSize = 0;
6584ba319b5SDimitry Andric     if (II.HasFocusFunction && !II.DataFlowTraceForFocusFunction.empty() &&
6594ba319b5SDimitry Andric         Size <= CurrentMaxMutationLen)
6604ba319b5SDimitry Andric       NewSize = MD.MutateWithMask(CurrentUnitData, Size, Size,
6614ba319b5SDimitry Andric                                   II.DataFlowTraceForFocusFunction);
6624ba319b5SDimitry Andric     else
6634ba319b5SDimitry Andric       NewSize = MD.Mutate(CurrentUnitData, Size, CurrentMaxMutationLen);
6644ba319b5SDimitry Andric     assert(NewSize > 0 && "Mutator returned empty unit");
6654ba319b5SDimitry Andric     assert(NewSize <= CurrentMaxMutationLen && "Mutator return oversized unit");
6664ba319b5SDimitry Andric     Size = NewSize;
6674ba319b5SDimitry Andric     II.NumExecutedMutations++;
6684ba319b5SDimitry Andric 
6694ba319b5SDimitry Andric     bool FoundUniqFeatures = false;
6704ba319b5SDimitry Andric     bool NewCov = RunOne(CurrentUnitData, Size, /*MayDeleteFile=*/true, &II,
6714ba319b5SDimitry Andric                          &FoundUniqFeatures);
6724ba319b5SDimitry Andric     TryDetectingAMemoryLeak(CurrentUnitData, Size,
6734ba319b5SDimitry Andric                             /*DuringInitialCorpusExecution*/ false);
6744ba319b5SDimitry Andric     if (NewCov) {
6754ba319b5SDimitry Andric       ReportNewCoverage(&II, {CurrentUnitData, CurrentUnitData + Size});
6764ba319b5SDimitry Andric       break;  // We will mutate this input more in the next rounds.
6774ba319b5SDimitry Andric     }
6784ba319b5SDimitry Andric     if (Options.ReduceDepth && !FoundUniqFeatures)
6794ba319b5SDimitry Andric         break;
6804ba319b5SDimitry Andric   }
6814ba319b5SDimitry Andric }
6824ba319b5SDimitry Andric 
PurgeAllocator()6834ba319b5SDimitry Andric void Fuzzer::PurgeAllocator() {
6844ba319b5SDimitry Andric   if (Options.PurgeAllocatorIntervalSec < 0 || !EF->__sanitizer_purge_allocator)
6854ba319b5SDimitry Andric     return;
6864ba319b5SDimitry Andric   if (duration_cast<seconds>(system_clock::now() -
6874ba319b5SDimitry Andric                              LastAllocatorPurgeAttemptTime)
6884ba319b5SDimitry Andric           .count() < Options.PurgeAllocatorIntervalSec)
6894ba319b5SDimitry Andric     return;
6904ba319b5SDimitry Andric 
6914ba319b5SDimitry Andric   if (Options.RssLimitMb <= 0 ||
6924ba319b5SDimitry Andric       GetPeakRSSMb() > static_cast<size_t>(Options.RssLimitMb) / 2)
6934ba319b5SDimitry Andric     EF->__sanitizer_purge_allocator();
6944ba319b5SDimitry Andric 
6954ba319b5SDimitry Andric   LastAllocatorPurgeAttemptTime = system_clock::now();
6964ba319b5SDimitry Andric }
6974ba319b5SDimitry Andric 
ReadAndExecuteSeedCorpora(const Vector<std::string> & CorpusDirs)6984ba319b5SDimitry Andric void Fuzzer::ReadAndExecuteSeedCorpora(const Vector<std::string> &CorpusDirs) {
6994ba319b5SDimitry Andric   const size_t kMaxSaneLen = 1 << 20;
7004ba319b5SDimitry Andric   const size_t kMinDefaultLen = 4096;
7014ba319b5SDimitry Andric   Vector<SizedFile> SizedFiles;
7024ba319b5SDimitry Andric   size_t MaxSize = 0;
7034ba319b5SDimitry Andric   size_t MinSize = -1;
7044ba319b5SDimitry Andric   size_t TotalSize = 0;
7054ba319b5SDimitry Andric   size_t LastNumFiles = 0;
7064ba319b5SDimitry Andric   for (auto &Dir : CorpusDirs) {
7074ba319b5SDimitry Andric     GetSizedFilesFromDir(Dir, &SizedFiles);
7084ba319b5SDimitry Andric     Printf("INFO: % 8zd files found in %s\n", SizedFiles.size() - LastNumFiles,
7094ba319b5SDimitry Andric            Dir.c_str());
7104ba319b5SDimitry Andric     LastNumFiles = SizedFiles.size();
7114ba319b5SDimitry Andric   }
7124ba319b5SDimitry Andric   for (auto &File : SizedFiles) {
7134ba319b5SDimitry Andric     MaxSize = Max(File.Size, MaxSize);
7144ba319b5SDimitry Andric     MinSize = Min(File.Size, MinSize);
7154ba319b5SDimitry Andric     TotalSize += File.Size;
7164ba319b5SDimitry Andric   }
7174ba319b5SDimitry Andric   if (Options.MaxLen == 0)
7184ba319b5SDimitry Andric     SetMaxInputLen(std::min(std::max(kMinDefaultLen, MaxSize), kMaxSaneLen));
7194ba319b5SDimitry Andric   assert(MaxInputLen > 0);
7204ba319b5SDimitry Andric 
7214ba319b5SDimitry Andric   // Test the callback with empty input and never try it again.
7224ba319b5SDimitry Andric   uint8_t dummy = 0;
7234ba319b5SDimitry Andric   ExecuteCallback(&dummy, 0);
7244ba319b5SDimitry Andric 
7254ba319b5SDimitry Andric   if (SizedFiles.empty()) {
7264ba319b5SDimitry Andric     Printf("INFO: A corpus is not provided, starting from an empty corpus\n");
7274ba319b5SDimitry Andric     Unit U({'\n'}); // Valid ASCII input.
7284ba319b5SDimitry Andric     RunOne(U.data(), U.size());
7294ba319b5SDimitry Andric   } else {
7304ba319b5SDimitry Andric     Printf("INFO: seed corpus: files: %zd min: %zdb max: %zdb total: %zdb"
7314ba319b5SDimitry Andric            " rss: %zdMb\n",
7324ba319b5SDimitry Andric            SizedFiles.size(), MinSize, MaxSize, TotalSize, GetPeakRSSMb());
7334ba319b5SDimitry Andric     if (Options.ShuffleAtStartUp)
7344ba319b5SDimitry Andric       std::shuffle(SizedFiles.begin(), SizedFiles.end(), MD.GetRand());
7354ba319b5SDimitry Andric 
7364ba319b5SDimitry Andric     if (Options.PreferSmall) {
7374ba319b5SDimitry Andric       std::stable_sort(SizedFiles.begin(), SizedFiles.end());
7384ba319b5SDimitry Andric       assert(SizedFiles.front().Size <= SizedFiles.back().Size);
7394ba319b5SDimitry Andric     }
7404ba319b5SDimitry Andric 
7414ba319b5SDimitry Andric     // Load and execute inputs one by one.
7424ba319b5SDimitry Andric     for (auto &SF : SizedFiles) {
7434ba319b5SDimitry Andric       auto U = FileToVector(SF.File, MaxInputLen, /*ExitOnError=*/false);
7444ba319b5SDimitry Andric       assert(U.size() <= MaxInputLen);
7454ba319b5SDimitry Andric       RunOne(U.data(), U.size());
7464ba319b5SDimitry Andric       CheckExitOnSrcPosOrItem();
7474ba319b5SDimitry Andric       TryDetectingAMemoryLeak(U.data(), U.size(),
7484ba319b5SDimitry Andric                               /*DuringInitialCorpusExecution*/ true);
7494ba319b5SDimitry Andric     }
7504ba319b5SDimitry Andric   }
7514ba319b5SDimitry Andric 
7524ba319b5SDimitry Andric   PrintStats("INITED");
7534ba319b5SDimitry Andric   if (!Options.FocusFunction.empty())
7544ba319b5SDimitry Andric     Printf("INFO: %zd/%zd inputs touch the focus function\n",
7554ba319b5SDimitry Andric            Corpus.NumInputsThatTouchFocusFunction(), Corpus.size());
7564ba319b5SDimitry Andric   if (!Options.DataFlowTrace.empty())
7574ba319b5SDimitry Andric     Printf("INFO: %zd/%zd inputs have the Data Flow Trace\n",
7584ba319b5SDimitry Andric            Corpus.NumInputsWithDataFlowTrace(), Corpus.size());
7594ba319b5SDimitry Andric 
7604ba319b5SDimitry Andric   if (Corpus.empty() && Options.MaxNumberOfRuns) {
7614ba319b5SDimitry Andric     Printf("ERROR: no interesting inputs were found. "
7624ba319b5SDimitry Andric            "Is the code instrumented for coverage? Exiting.\n");
7634ba319b5SDimitry Andric     exit(1);
7644ba319b5SDimitry Andric   }
7654ba319b5SDimitry Andric }
7664ba319b5SDimitry Andric 
Loop(const Vector<std::string> & CorpusDirs)7674ba319b5SDimitry Andric void Fuzzer::Loop(const Vector<std::string> &CorpusDirs) {
7684ba319b5SDimitry Andric   ReadAndExecuteSeedCorpora(CorpusDirs);
7694ba319b5SDimitry Andric   DFT.Clear();  // No need for DFT any more.
7704ba319b5SDimitry Andric   TPC.SetPrintNewPCs(Options.PrintNewCovPcs);
7714ba319b5SDimitry Andric   TPC.SetPrintNewFuncs(Options.PrintNewCovFuncs);
7724ba319b5SDimitry Andric   system_clock::time_point LastCorpusReload = system_clock::now();
7734ba319b5SDimitry Andric   if (Options.DoCrossOver)
7744ba319b5SDimitry Andric     MD.SetCorpus(&Corpus);
7754ba319b5SDimitry Andric   while (true) {
7764ba319b5SDimitry Andric     auto Now = system_clock::now();
7774ba319b5SDimitry Andric     if (duration_cast<seconds>(Now - LastCorpusReload).count() >=
7784ba319b5SDimitry Andric         Options.ReloadIntervalSec) {
7794ba319b5SDimitry Andric       RereadOutputCorpus(MaxInputLen);
7804ba319b5SDimitry Andric       LastCorpusReload = system_clock::now();
7814ba319b5SDimitry Andric     }
7824ba319b5SDimitry Andric     if (TotalNumberOfRuns >= Options.MaxNumberOfRuns)
7834ba319b5SDimitry Andric       break;
7844ba319b5SDimitry Andric     if (TimedOut())
7854ba319b5SDimitry Andric       break;
7864ba319b5SDimitry Andric 
7874ba319b5SDimitry Andric     // Update TmpMaxMutationLen
7884ba319b5SDimitry Andric     if (Options.LenControl) {
7894ba319b5SDimitry Andric       if (TmpMaxMutationLen < MaxMutationLen &&
7904ba319b5SDimitry Andric           TotalNumberOfRuns - LastCorpusUpdateRun >
7914ba319b5SDimitry Andric               Options.LenControl * Log(TmpMaxMutationLen)) {
7924ba319b5SDimitry Andric         TmpMaxMutationLen =
7934ba319b5SDimitry Andric             Min(MaxMutationLen, TmpMaxMutationLen + Log(TmpMaxMutationLen));
7944ba319b5SDimitry Andric         LastCorpusUpdateRun = TotalNumberOfRuns;
7954ba319b5SDimitry Andric       }
7964ba319b5SDimitry Andric     } else {
7974ba319b5SDimitry Andric       TmpMaxMutationLen = MaxMutationLen;
7984ba319b5SDimitry Andric     }
7994ba319b5SDimitry Andric 
8004ba319b5SDimitry Andric     // Perform several mutations and runs.
8014ba319b5SDimitry Andric     MutateAndTestOne();
8024ba319b5SDimitry Andric 
8034ba319b5SDimitry Andric     PurgeAllocator();
8044ba319b5SDimitry Andric   }
8054ba319b5SDimitry Andric 
8064ba319b5SDimitry Andric   PrintStats("DONE  ", "\n");
8074ba319b5SDimitry Andric   MD.PrintRecommendedDictionary();
8084ba319b5SDimitry Andric }
8094ba319b5SDimitry Andric 
MinimizeCrashLoop(const Unit & U)8104ba319b5SDimitry Andric void Fuzzer::MinimizeCrashLoop(const Unit &U) {
8114ba319b5SDimitry Andric   if (U.size() <= 1)
8124ba319b5SDimitry Andric     return;
8134ba319b5SDimitry Andric   while (!TimedOut() && TotalNumberOfRuns < Options.MaxNumberOfRuns) {
8144ba319b5SDimitry Andric     MD.StartMutationSequence();
8154ba319b5SDimitry Andric     memcpy(CurrentUnitData, U.data(), U.size());
8164ba319b5SDimitry Andric     for (int i = 0; i < Options.MutateDepth; i++) {
8174ba319b5SDimitry Andric       size_t NewSize = MD.Mutate(CurrentUnitData, U.size(), MaxMutationLen);
8184ba319b5SDimitry Andric       assert(NewSize > 0 && NewSize <= MaxMutationLen);
8194ba319b5SDimitry Andric       ExecuteCallback(CurrentUnitData, NewSize);
8204ba319b5SDimitry Andric       PrintPulseAndReportSlowInput(CurrentUnitData, NewSize);
8214ba319b5SDimitry Andric       TryDetectingAMemoryLeak(CurrentUnitData, NewSize,
8224ba319b5SDimitry Andric                               /*DuringInitialCorpusExecution*/ false);
8234ba319b5SDimitry Andric     }
8244ba319b5SDimitry Andric   }
8254ba319b5SDimitry Andric }
8264ba319b5SDimitry Andric 
AnnounceOutput(const uint8_t * Data,size_t Size)8274ba319b5SDimitry Andric void Fuzzer::AnnounceOutput(const uint8_t *Data, size_t Size) {
8284ba319b5SDimitry Andric   if (SMR.IsServer()) {
8294ba319b5SDimitry Andric     SMR.WriteByteArray(Data, Size);
8304ba319b5SDimitry Andric   } else if (SMR.IsClient()) {
8314ba319b5SDimitry Andric     SMR.PostClient();
8324ba319b5SDimitry Andric     SMR.WaitServer();
8334ba319b5SDimitry Andric     size_t OtherSize = SMR.ReadByteArraySize();
8344ba319b5SDimitry Andric     uint8_t *OtherData = SMR.GetByteArray();
8354ba319b5SDimitry Andric     if (Size != OtherSize || memcmp(Data, OtherData, Size) != 0) {
8364ba319b5SDimitry Andric       size_t i = 0;
8374ba319b5SDimitry Andric       for (i = 0; i < Min(Size, OtherSize); i++)
8384ba319b5SDimitry Andric         if (Data[i] != OtherData[i])
8394ba319b5SDimitry Andric           break;
8404ba319b5SDimitry Andric       Printf("==%lu== ERROR: libFuzzer: equivalence-mismatch. Sizes: %zd %zd; "
8414ba319b5SDimitry Andric              "offset %zd\n",
8424ba319b5SDimitry Andric              GetPid(), Size, OtherSize, i);
8434ba319b5SDimitry Andric       DumpCurrentUnit("mismatch-");
8444ba319b5SDimitry Andric       Printf("SUMMARY: libFuzzer: equivalence-mismatch\n");
8454ba319b5SDimitry Andric       PrintFinalStats();
8464ba319b5SDimitry Andric       _Exit(Options.ErrorExitCode);
8474ba319b5SDimitry Andric     }
8484ba319b5SDimitry Andric   }
8494ba319b5SDimitry Andric }
8504ba319b5SDimitry Andric 
8514ba319b5SDimitry Andric } // namespace fuzzer
8524ba319b5SDimitry Andric 
8534ba319b5SDimitry Andric extern "C" {
8544ba319b5SDimitry Andric 
8554ba319b5SDimitry Andric __attribute__((visibility("default"))) size_t
LLVMFuzzerMutate(uint8_t * Data,size_t Size,size_t MaxSize)8564ba319b5SDimitry Andric LLVMFuzzerMutate(uint8_t *Data, size_t Size, size_t MaxSize) {
8574ba319b5SDimitry Andric   assert(fuzzer::F);
8584ba319b5SDimitry Andric   return fuzzer::F->GetMD().DefaultMutate(Data, Size, MaxSize);
8594ba319b5SDimitry Andric }
8604ba319b5SDimitry Andric 
8614ba319b5SDimitry Andric // Experimental
8624ba319b5SDimitry Andric __attribute__((visibility("default"))) void
LLVMFuzzerAnnounceOutput(const uint8_t * Data,size_t Size)8634ba319b5SDimitry Andric LLVMFuzzerAnnounceOutput(const uint8_t *Data, size_t Size) {
8644ba319b5SDimitry Andric   assert(fuzzer::F);
8654ba319b5SDimitry Andric   fuzzer::F->AnnounceOutput(Data, Size);
8664ba319b5SDimitry Andric }
8674ba319b5SDimitry Andric } // extern "C"
868