Home | History | Annotate | Line # | Download | only in fuzzer
      1  1.1  kamil //===- FuzzerLoop.cpp - Fuzzer's main loop --------------------------------===//
      2  1.1  kamil //
      3  1.1  kamil //                     The LLVM Compiler Infrastructure
      4  1.1  kamil //
      5  1.1  kamil // This file is distributed under the University of Illinois Open Source
      6  1.1  kamil // License. See LICENSE.TXT for details.
      7  1.1  kamil //
      8  1.1  kamil //===----------------------------------------------------------------------===//
      9  1.1  kamil // Fuzzer's main loop.
     10  1.1  kamil //===----------------------------------------------------------------------===//
     11  1.1  kamil 
     12  1.1  kamil #include "FuzzerCorpus.h"
     13  1.1  kamil #include "FuzzerIO.h"
     14  1.1  kamil #include "FuzzerInternal.h"
     15  1.1  kamil #include "FuzzerMutate.h"
     16  1.1  kamil #include "FuzzerRandom.h"
     17  1.1  kamil #include "FuzzerShmem.h"
     18  1.1  kamil #include "FuzzerTracePC.h"
     19  1.1  kamil #include <algorithm>
     20  1.1  kamil #include <cstring>
     21  1.1  kamil #include <memory>
     22  1.1  kamil #include <mutex>
     23  1.1  kamil #include <set>
     24  1.1  kamil 
     25  1.1  kamil #if defined(__has_include)
     26  1.1  kamil #if __has_include(<sanitizer / lsan_interface.h>)
     27  1.1  kamil #include <sanitizer/lsan_interface.h>
     28  1.1  kamil #endif
     29  1.1  kamil #endif
     30  1.1  kamil 
     31  1.1  kamil #define NO_SANITIZE_MEMORY
     32  1.1  kamil #if defined(__has_feature)
     33  1.1  kamil #if __has_feature(memory_sanitizer)
     34  1.1  kamil #undef NO_SANITIZE_MEMORY
     35  1.1  kamil #define NO_SANITIZE_MEMORY __attribute__((no_sanitize_memory))
     36  1.1  kamil #endif
     37  1.1  kamil #endif
     38  1.1  kamil 
     39  1.1  kamil namespace fuzzer {
     40  1.1  kamil static const size_t kMaxUnitSizeToPrint = 256;
     41  1.1  kamil 
     42  1.1  kamil thread_local bool Fuzzer::IsMyThread;
     43  1.1  kamil 
     44  1.1  kamil SharedMemoryRegion SMR;
     45  1.1  kamil 
     46  1.1  kamil bool RunningUserCallback = false;
     47  1.1  kamil 
     48  1.1  kamil // Only one Fuzzer per process.
     49  1.1  kamil static Fuzzer *F;
     50  1.1  kamil 
     51  1.1  kamil // Leak detection is expensive, so we first check if there were more mallocs
     52  1.1  kamil // than frees (using the sanitizer malloc hooks) and only then try to call lsan.
     53  1.1  kamil struct MallocFreeTracer {
     54  1.1  kamil   void Start(int TraceLevel) {
     55  1.1  kamil     this->TraceLevel = TraceLevel;
     56  1.1  kamil     if (TraceLevel)
     57  1.1  kamil       Printf("MallocFreeTracer: START\n");
     58  1.1  kamil     Mallocs = 0;
     59  1.1  kamil     Frees = 0;
     60  1.1  kamil   }
     61  1.1  kamil   // Returns true if there were more mallocs than frees.
     62  1.1  kamil   bool Stop() {
     63  1.1  kamil     if (TraceLevel)
     64  1.1  kamil       Printf("MallocFreeTracer: STOP %zd %zd (%s)\n", Mallocs.load(),
     65  1.1  kamil              Frees.load(), Mallocs == Frees ? "same" : "DIFFERENT");
     66  1.1  kamil     bool Result = Mallocs > Frees;
     67  1.1  kamil     Mallocs = 0;
     68  1.1  kamil     Frees = 0;
     69  1.1  kamil     TraceLevel = 0;
     70  1.1  kamil     return Result;
     71  1.1  kamil   }
     72  1.1  kamil   std::atomic<size_t> Mallocs;
     73  1.1  kamil   std::atomic<size_t> Frees;
     74  1.1  kamil   int TraceLevel = 0;
     75  1.1  kamil 
     76  1.1  kamil   std::recursive_mutex TraceMutex;
     77  1.1  kamil   bool TraceDisabled = false;
     78  1.1  kamil };
     79  1.1  kamil 
     80  1.1  kamil static MallocFreeTracer AllocTracer;
     81  1.1  kamil 
     82  1.1  kamil // Locks printing and avoids nested hooks triggered from mallocs/frees in
     83  1.1  kamil // sanitizer.
     84  1.1  kamil class TraceLock {
     85  1.1  kamil public:
     86  1.1  kamil   TraceLock() : Lock(AllocTracer.TraceMutex) {
     87  1.1  kamil     AllocTracer.TraceDisabled = !AllocTracer.TraceDisabled;
     88  1.1  kamil   }
     89  1.1  kamil   ~TraceLock() { AllocTracer.TraceDisabled = !AllocTracer.TraceDisabled; }
     90  1.1  kamil 
     91  1.1  kamil   bool IsDisabled() const {
     92  1.1  kamil     // This is already inverted value.
     93  1.1  kamil     return !AllocTracer.TraceDisabled;
     94  1.1  kamil   }
     95  1.1  kamil 
     96  1.1  kamil private:
     97  1.1  kamil   std::lock_guard<std::recursive_mutex> Lock;
     98  1.1  kamil };
     99  1.1  kamil 
    100  1.1  kamil ATTRIBUTE_NO_SANITIZE_MEMORY
    101  1.1  kamil void MallocHook(const volatile void *ptr, size_t size) {
    102  1.1  kamil   size_t N = AllocTracer.Mallocs++;
    103  1.1  kamil   F->HandleMalloc(size);
    104  1.1  kamil   if (int TraceLevel = AllocTracer.TraceLevel) {
    105  1.1  kamil     TraceLock Lock;
    106  1.1  kamil     if (Lock.IsDisabled())
    107  1.1  kamil       return;
    108  1.1  kamil     Printf("MALLOC[%zd] %p %zd\n", N, ptr, size);
    109  1.1  kamil     if (TraceLevel >= 2 && EF)
    110  1.1  kamil       PrintStackTrace();
    111  1.1  kamil   }
    112  1.1  kamil }
    113  1.1  kamil 
    114  1.1  kamil ATTRIBUTE_NO_SANITIZE_MEMORY
    115  1.1  kamil void FreeHook(const volatile void *ptr) {
    116  1.1  kamil   size_t N = AllocTracer.Frees++;
    117  1.1  kamil   if (int TraceLevel = AllocTracer.TraceLevel) {
    118  1.1  kamil     TraceLock Lock;
    119  1.1  kamil     if (Lock.IsDisabled())
    120  1.1  kamil       return;
    121  1.1  kamil     Printf("FREE[%zd]   %p\n", N, ptr);
    122  1.1  kamil     if (TraceLevel >= 2 && EF)
    123  1.1  kamil       PrintStackTrace();
    124  1.1  kamil   }
    125  1.1  kamil }
    126  1.1  kamil 
    127  1.1  kamil // Crash on a single malloc that exceeds the rss limit.
    128  1.1  kamil void Fuzzer::HandleMalloc(size_t Size) {
    129  1.1  kamil   if (!Options.MallocLimitMb || (Size >> 20) < (size_t)Options.MallocLimitMb)
    130  1.1  kamil     return;
    131  1.1  kamil   Printf("==%d== ERROR: libFuzzer: out-of-memory (malloc(%zd))\n", GetPid(),
    132  1.1  kamil          Size);
    133  1.1  kamil   Printf("   To change the out-of-memory limit use -rss_limit_mb=<N>\n\n");
    134  1.1  kamil   PrintStackTrace();
    135  1.1  kamil   DumpCurrentUnit("oom-");
    136  1.1  kamil   Printf("SUMMARY: libFuzzer: out-of-memory\n");
    137  1.1  kamil   PrintFinalStats();
    138  1.1  kamil   _Exit(Options.ErrorExitCode); // Stop right now.
    139  1.1  kamil }
    140  1.1  kamil 
    141  1.1  kamil Fuzzer::Fuzzer(UserCallback CB, InputCorpus &Corpus, MutationDispatcher &MD,
    142  1.1  kamil                FuzzingOptions Options)
    143  1.1  kamil     : CB(CB), Corpus(Corpus), MD(MD), Options(Options) {
    144  1.1  kamil   if (EF->__sanitizer_set_death_callback)
    145  1.1  kamil     EF->__sanitizer_set_death_callback(StaticDeathCallback);
    146  1.1  kamil   assert(!F);
    147  1.1  kamil   F = this;
    148  1.1  kamil   TPC.ResetMaps();
    149  1.1  kamil   IsMyThread = true;
    150  1.1  kamil   if (Options.DetectLeaks && EF->__sanitizer_install_malloc_and_free_hooks)
    151  1.1  kamil     EF->__sanitizer_install_malloc_and_free_hooks(MallocHook, FreeHook);
    152  1.1  kamil   TPC.SetUseCounters(Options.UseCounters);
    153  1.1  kamil   TPC.SetUseValueProfileMask(Options.UseValueProfile);
    154  1.1  kamil 
    155  1.1  kamil   if (Options.Verbosity)
    156  1.1  kamil     TPC.PrintModuleInfo();
    157  1.1  kamil   if (!Options.OutputCorpus.empty() && Options.ReloadIntervalSec)
    158  1.1  kamil     EpochOfLastReadOfOutputCorpus = GetEpoch(Options.OutputCorpus);
    159  1.1  kamil   MaxInputLen = MaxMutationLen = Options.MaxLen;
    160  1.1  kamil   TmpMaxMutationLen = Max(size_t(4), Corpus.MaxInputSize());
    161  1.1  kamil   AllocateCurrentUnitData();
    162  1.1  kamil   CurrentUnitSize = 0;
    163  1.1  kamil   memset(BaseSha1, 0, sizeof(BaseSha1));
    164  1.1  kamil   TPC.SetFocusFunction(Options.FocusFunction);
    165  1.1  kamil   DFT.Init(Options.DataFlowTrace, Options.FocusFunction);
    166  1.1  kamil }
    167  1.1  kamil 
    168  1.1  kamil Fuzzer::~Fuzzer() {}
    169  1.1  kamil 
    170  1.1  kamil void Fuzzer::AllocateCurrentUnitData() {
    171  1.1  kamil   if (CurrentUnitData || MaxInputLen == 0)
    172  1.1  kamil     return;
    173  1.1  kamil   CurrentUnitData = new uint8_t[MaxInputLen];
    174  1.1  kamil }
    175  1.1  kamil 
    176  1.1  kamil void Fuzzer::StaticDeathCallback() {
    177  1.1  kamil   assert(F);
    178  1.1  kamil   F->DeathCallback();
    179  1.1  kamil }
    180  1.1  kamil 
    181  1.1  kamil void Fuzzer::DumpCurrentUnit(const char *Prefix) {
    182  1.1  kamil   if (!CurrentUnitData)
    183  1.1  kamil     return; // Happens when running individual inputs.
    184  1.1  kamil   ScopedDisableMsanInterceptorChecks S;
    185  1.1  kamil   MD.PrintMutationSequence();
    186  1.1  kamil   Printf("; base unit: %s\n", Sha1ToString(BaseSha1).c_str());
    187  1.1  kamil   size_t UnitSize = CurrentUnitSize;
    188  1.1  kamil   if (UnitSize <= kMaxUnitSizeToPrint) {
    189  1.1  kamil     PrintHexArray(CurrentUnitData, UnitSize, "\n");
    190  1.1  kamil     PrintASCII(CurrentUnitData, UnitSize, "\n");
    191  1.1  kamil   }
    192  1.1  kamil   WriteUnitToFileWithPrefix({CurrentUnitData, CurrentUnitData + UnitSize},
    193  1.1  kamil                             Prefix);
    194  1.1  kamil }
    195  1.1  kamil 
    196  1.1  kamil NO_SANITIZE_MEMORY
    197  1.1  kamil void Fuzzer::DeathCallback() {
    198  1.1  kamil   DumpCurrentUnit("crash-");
    199  1.1  kamil   PrintFinalStats();
    200  1.1  kamil }
    201  1.1  kamil 
    202  1.1  kamil void Fuzzer::StaticAlarmCallback() {
    203  1.1  kamil   assert(F);
    204  1.1  kamil   F->AlarmCallback();
    205  1.1  kamil }
    206  1.1  kamil 
    207  1.1  kamil void Fuzzer::StaticCrashSignalCallback() {
    208  1.1  kamil   assert(F);
    209  1.1  kamil   F->CrashCallback();
    210  1.1  kamil }
    211  1.1  kamil 
    212  1.1  kamil void Fuzzer::StaticExitCallback() {
    213  1.1  kamil   assert(F);
    214  1.1  kamil   F->ExitCallback();
    215  1.1  kamil }
    216  1.1  kamil 
    217  1.1  kamil void Fuzzer::StaticInterruptCallback() {
    218  1.1  kamil   assert(F);
    219  1.1  kamil   F->InterruptCallback();
    220  1.1  kamil }
    221  1.1  kamil 
    222  1.1  kamil void Fuzzer::StaticGracefulExitCallback() {
    223  1.1  kamil   assert(F);
    224  1.1  kamil   F->GracefulExitRequested = true;
    225  1.1  kamil   Printf("INFO: signal received, trying to exit gracefully\n");
    226  1.1  kamil }
    227  1.1  kamil 
    228  1.1  kamil void Fuzzer::StaticFileSizeExceedCallback() {
    229  1.1  kamil   Printf("==%lu== ERROR: libFuzzer: file size exceeded\n", GetPid());
    230  1.1  kamil   exit(1);
    231  1.1  kamil }
    232  1.1  kamil 
    233  1.1  kamil void Fuzzer::CrashCallback() {
    234  1.1  kamil   if (EF->__sanitizer_acquire_crash_state)
    235  1.1  kamil     EF->__sanitizer_acquire_crash_state();
    236  1.1  kamil   Printf("==%lu== ERROR: libFuzzer: deadly signal\n", GetPid());
    237  1.1  kamil   PrintStackTrace();
    238  1.1  kamil   Printf("NOTE: libFuzzer has rudimentary signal handlers.\n"
    239  1.1  kamil          "      Combine libFuzzer with AddressSanitizer or similar for better "
    240  1.1  kamil          "crash reports.\n");
    241  1.1  kamil   Printf("SUMMARY: libFuzzer: deadly signal\n");
    242  1.1  kamil   DumpCurrentUnit("crash-");
    243  1.1  kamil   PrintFinalStats();
    244  1.1  kamil   _Exit(Options.ErrorExitCode); // Stop right now.
    245  1.1  kamil }
    246  1.1  kamil 
    247  1.1  kamil void Fuzzer::ExitCallback() {
    248  1.1  kamil   if (!RunningUserCallback)
    249  1.1  kamil     return; // This exit did not come from the user callback
    250  1.1  kamil   if (EF->__sanitizer_acquire_crash_state &&
    251  1.1  kamil       !EF->__sanitizer_acquire_crash_state())
    252  1.1  kamil     return;
    253  1.1  kamil   Printf("==%lu== ERROR: libFuzzer: fuzz target exited\n", GetPid());
    254  1.1  kamil   PrintStackTrace();
    255  1.1  kamil   Printf("SUMMARY: libFuzzer: fuzz target exited\n");
    256  1.1  kamil   DumpCurrentUnit("crash-");
    257  1.1  kamil   PrintFinalStats();
    258  1.1  kamil   _Exit(Options.ErrorExitCode);
    259  1.1  kamil }
    260  1.1  kamil 
    261  1.1  kamil void Fuzzer::MaybeExitGracefully() {
    262  1.1  kamil   if (!GracefulExitRequested) return;
    263  1.1  kamil   Printf("==%lu== INFO: libFuzzer: exiting as requested\n", GetPid());
    264  1.1  kamil   PrintFinalStats();
    265  1.1  kamil   _Exit(0);
    266  1.1  kamil }
    267  1.1  kamil 
    268  1.1  kamil void Fuzzer::InterruptCallback() {
    269  1.1  kamil   Printf("==%lu== libFuzzer: run interrupted; exiting\n", GetPid());
    270  1.1  kamil   PrintFinalStats();
    271  1.1  kamil   _Exit(0); // Stop right now, don't perform any at-exit actions.
    272  1.1  kamil }
    273  1.1  kamil 
    274  1.1  kamil NO_SANITIZE_MEMORY
    275  1.1  kamil void Fuzzer::AlarmCallback() {
    276  1.1  kamil   assert(Options.UnitTimeoutSec > 0);
    277  1.1  kamil   // In Windows Alarm callback is executed by a different thread.
    278  1.1  kamil   // NetBSD's current behavior needs this change too.
    279  1.1  kamil #if !LIBFUZZER_WINDOWS && !LIBFUZZER_NETBSD
    280  1.1  kamil   if (!InFuzzingThread())
    281  1.1  kamil     return;
    282  1.1  kamil #endif
    283  1.1  kamil   if (!RunningUserCallback)
    284  1.1  kamil     return; // We have not started running units yet.
    285  1.1  kamil   size_t Seconds =
    286  1.1  kamil       duration_cast<seconds>(system_clock::now() - UnitStartTime).count();
    287  1.1  kamil   if (Seconds == 0)
    288  1.1  kamil     return;
    289  1.1  kamil   if (Options.Verbosity >= 2)
    290  1.1  kamil     Printf("AlarmCallback %zd\n", Seconds);
    291  1.1  kamil   if (Seconds >= (size_t)Options.UnitTimeoutSec) {
    292  1.1  kamil     if (EF->__sanitizer_acquire_crash_state &&
    293  1.1  kamil         !EF->__sanitizer_acquire_crash_state())
    294  1.1  kamil       return;
    295  1.1  kamil     Printf("ALARM: working on the last Unit for %zd seconds\n", Seconds);
    296  1.1  kamil     Printf("       and the timeout value is %d (use -timeout=N to change)\n",
    297  1.1  kamil            Options.UnitTimeoutSec);
    298  1.1  kamil     DumpCurrentUnit("timeout-");
    299  1.1  kamil     Printf("==%lu== ERROR: libFuzzer: timeout after %d seconds\n", GetPid(),
    300  1.1  kamil            Seconds);
    301  1.1  kamil     PrintStackTrace();
    302  1.1  kamil     Printf("SUMMARY: libFuzzer: timeout\n");
    303  1.1  kamil     PrintFinalStats();
    304  1.1  kamil     _Exit(Options.TimeoutExitCode); // Stop right now.
    305  1.1  kamil   }
    306  1.1  kamil }
    307  1.1  kamil 
    308  1.1  kamil void Fuzzer::RssLimitCallback() {
    309  1.1  kamil   if (EF->__sanitizer_acquire_crash_state &&
    310  1.1  kamil       !EF->__sanitizer_acquire_crash_state())
    311  1.1  kamil     return;
    312  1.1  kamil   Printf(
    313  1.1  kamil       "==%lu== ERROR: libFuzzer: out-of-memory (used: %zdMb; limit: %zdMb)\n",
    314  1.1  kamil       GetPid(), GetPeakRSSMb(), Options.RssLimitMb);
    315  1.1  kamil   Printf("   To change the out-of-memory limit use -rss_limit_mb=<N>\n\n");
    316  1.1  kamil   PrintMemoryProfile();
    317  1.1  kamil   DumpCurrentUnit("oom-");
    318  1.1  kamil   Printf("SUMMARY: libFuzzer: out-of-memory\n");
    319  1.1  kamil   PrintFinalStats();
    320  1.1  kamil   _Exit(Options.ErrorExitCode); // Stop right now.
    321  1.1  kamil }
    322  1.1  kamil 
    323  1.1  kamil void Fuzzer::PrintStats(const char *Where, const char *End, size_t Units) {
    324  1.1  kamil   size_t ExecPerSec = execPerSec();
    325  1.1  kamil   if (!Options.Verbosity)
    326  1.1  kamil     return;
    327  1.1  kamil   Printf("#%zd\t%s", TotalNumberOfRuns, Where);
    328  1.1  kamil   if (size_t N = TPC.GetTotalPCCoverage())
    329  1.1  kamil     Printf(" cov: %zd", N);
    330  1.1  kamil   if (size_t N = Corpus.NumFeatures())
    331  1.1  kamil     Printf(" ft: %zd", N);
    332  1.1  kamil   if (!Corpus.empty()) {
    333  1.1  kamil     Printf(" corp: %zd", Corpus.NumActiveUnits());
    334  1.1  kamil     if (size_t N = Corpus.SizeInBytes()) {
    335  1.1  kamil       if (N < (1 << 14))
    336  1.1  kamil         Printf("/%zdb", N);
    337  1.1  kamil       else if (N < (1 << 24))
    338  1.1  kamil         Printf("/%zdKb", N >> 10);
    339  1.1  kamil       else
    340  1.1  kamil         Printf("/%zdMb", N >> 20);
    341  1.1  kamil     }
    342  1.1  kamil     if (size_t FF = Corpus.NumInputsThatTouchFocusFunction())
    343  1.1  kamil       Printf(" focus: %zd", FF);
    344  1.1  kamil   }
    345  1.1  kamil   if (TmpMaxMutationLen)
    346  1.1  kamil     Printf(" lim: %zd", TmpMaxMutationLen);
    347  1.1  kamil   if (Units)
    348  1.1  kamil     Printf(" units: %zd", Units);
    349  1.1  kamil 
    350  1.1  kamil   Printf(" exec/s: %zd", ExecPerSec);
    351  1.1  kamil   Printf(" rss: %zdMb", GetPeakRSSMb());
    352  1.1  kamil   Printf("%s", End);
    353  1.1  kamil }
    354  1.1  kamil 
    355  1.1  kamil void Fuzzer::PrintFinalStats() {
    356  1.1  kamil   if (Options.PrintCoverage)
    357  1.1  kamil     TPC.PrintCoverage();
    358  1.1  kamil   if (Options.PrintUnstableStats)
    359  1.1  kamil     TPC.PrintUnstableStats();
    360  1.1  kamil   if (Options.DumpCoverage)
    361  1.1  kamil     TPC.DumpCoverage();
    362  1.1  kamil   if (Options.PrintCorpusStats)
    363  1.1  kamil     Corpus.PrintStats();
    364  1.1  kamil   if (!Options.PrintFinalStats)
    365  1.1  kamil     return;
    366  1.1  kamil   size_t ExecPerSec = execPerSec();
    367  1.1  kamil   Printf("stat::number_of_executed_units: %zd\n", TotalNumberOfRuns);
    368  1.1  kamil   Printf("stat::average_exec_per_sec:     %zd\n", ExecPerSec);
    369  1.1  kamil   Printf("stat::new_units_added:          %zd\n", NumberOfNewUnitsAdded);
    370  1.1  kamil   Printf("stat::slowest_unit_time_sec:    %zd\n", TimeOfLongestUnitInSeconds);
    371  1.1  kamil   Printf("stat::peak_rss_mb:              %zd\n", GetPeakRSSMb());
    372  1.1  kamil }
    373  1.1  kamil 
    374  1.1  kamil void Fuzzer::SetMaxInputLen(size_t MaxInputLen) {
    375  1.1  kamil   assert(this->MaxInputLen == 0); // Can only reset MaxInputLen from 0 to non-0.
    376  1.1  kamil   assert(MaxInputLen);
    377  1.1  kamil   this->MaxInputLen = MaxInputLen;
    378  1.1  kamil   this->MaxMutationLen = MaxInputLen;
    379  1.1  kamil   AllocateCurrentUnitData();
    380  1.1  kamil   Printf("INFO: -max_len is not provided; "
    381  1.1  kamil          "libFuzzer will not generate inputs larger than %zd bytes\n",
    382  1.1  kamil          MaxInputLen);
    383  1.1  kamil }
    384  1.1  kamil 
    385  1.1  kamil void Fuzzer::SetMaxMutationLen(size_t MaxMutationLen) {
    386  1.1  kamil   assert(MaxMutationLen && MaxMutationLen <= MaxInputLen);
    387  1.1  kamil   this->MaxMutationLen = MaxMutationLen;
    388  1.1  kamil }
    389  1.1  kamil 
    390  1.1  kamil void Fuzzer::CheckExitOnSrcPosOrItem() {
    391  1.1  kamil   if (!Options.ExitOnSrcPos.empty()) {
    392  1.1  kamil     static auto *PCsSet = new Set<uintptr_t>;
    393  1.1  kamil     auto HandlePC = [&](uintptr_t PC) {
    394  1.1  kamil       if (!PCsSet->insert(PC).second)
    395  1.1  kamil         return;
    396  1.1  kamil       std::string Descr = DescribePC("%F %L", PC + 1);
    397  1.1  kamil       if (Descr.find(Options.ExitOnSrcPos) != std::string::npos) {
    398  1.1  kamil         Printf("INFO: found line matching '%s', exiting.\n",
    399  1.1  kamil                Options.ExitOnSrcPos.c_str());
    400  1.1  kamil         _Exit(0);
    401  1.1  kamil       }
    402  1.1  kamil     };
    403  1.1  kamil     TPC.ForEachObservedPC(HandlePC);
    404  1.1  kamil   }
    405  1.1  kamil   if (!Options.ExitOnItem.empty()) {
    406  1.1  kamil     if (Corpus.HasUnit(Options.ExitOnItem)) {
    407  1.1  kamil       Printf("INFO: found item with checksum '%s', exiting.\n",
    408  1.1  kamil              Options.ExitOnItem.c_str());
    409  1.1  kamil       _Exit(0);
    410  1.1  kamil     }
    411  1.1  kamil   }
    412  1.1  kamil }
    413  1.1  kamil 
    414  1.1  kamil void Fuzzer::RereadOutputCorpus(size_t MaxSize) {
    415  1.1  kamil   if (Options.OutputCorpus.empty() || !Options.ReloadIntervalSec)
    416  1.1  kamil     return;
    417  1.1  kamil   Vector<Unit> AdditionalCorpus;
    418  1.1  kamil   ReadDirToVectorOfUnits(Options.OutputCorpus.c_str(), &AdditionalCorpus,
    419  1.1  kamil                          &EpochOfLastReadOfOutputCorpus, MaxSize,
    420  1.1  kamil                          /*ExitOnError*/ false);
    421  1.1  kamil   if (Options.Verbosity >= 2)
    422  1.1  kamil     Printf("Reload: read %zd new units.\n", AdditionalCorpus.size());
    423  1.1  kamil   bool Reloaded = false;
    424  1.1  kamil   for (auto &U : AdditionalCorpus) {
    425  1.1  kamil     if (U.size() > MaxSize)
    426  1.1  kamil       U.resize(MaxSize);
    427  1.1  kamil     if (!Corpus.HasUnit(U)) {
    428  1.1  kamil       if (RunOne(U.data(), U.size())) {
    429  1.1  kamil         CheckExitOnSrcPosOrItem();
    430  1.1  kamil         Reloaded = true;
    431  1.1  kamil       }
    432  1.1  kamil     }
    433  1.1  kamil   }
    434  1.1  kamil   if (Reloaded)
    435  1.1  kamil     PrintStats("RELOAD");
    436  1.1  kamil }
    437  1.1  kamil 
    438  1.1  kamil void Fuzzer::PrintPulseAndReportSlowInput(const uint8_t *Data, size_t Size) {
    439  1.1  kamil   auto TimeOfUnit =
    440  1.1  kamil       duration_cast<seconds>(UnitStopTime - UnitStartTime).count();
    441  1.1  kamil   if (!(TotalNumberOfRuns & (TotalNumberOfRuns - 1)) &&
    442  1.1  kamil       secondsSinceProcessStartUp() >= 2)
    443  1.1  kamil     PrintStats("pulse ");
    444  1.1  kamil   if (TimeOfUnit > TimeOfLongestUnitInSeconds * 1.1 &&
    445  1.1  kamil       TimeOfUnit >= Options.ReportSlowUnits) {
    446  1.1  kamil     TimeOfLongestUnitInSeconds = TimeOfUnit;
    447  1.1  kamil     Printf("Slowest unit: %zd s:\n", TimeOfLongestUnitInSeconds);
    448  1.1  kamil     WriteUnitToFileWithPrefix({Data, Data + Size}, "slow-unit-");
    449  1.1  kamil   }
    450  1.1  kamil }
    451  1.1  kamil 
    452  1.1  kamil void Fuzzer::CheckForUnstableCounters(const uint8_t *Data, size_t Size) {
    453  1.1  kamil   auto CBSetupAndRun = [&]() {
    454  1.1  kamil     ScopedEnableMsanInterceptorChecks S;
    455  1.1  kamil     UnitStartTime = system_clock::now();
    456  1.1  kamil     TPC.ResetMaps();
    457  1.1  kamil     RunningUserCallback = true;
    458  1.1  kamil     CB(Data, Size);
    459  1.1  kamil     RunningUserCallback = false;
    460  1.1  kamil     UnitStopTime = system_clock::now();
    461  1.1  kamil   };
    462  1.1  kamil 
    463  1.1  kamil   // Copy original run counters into our unstable counters
    464  1.1  kamil   TPC.InitializeUnstableCounters();
    465  1.1  kamil 
    466  1.1  kamil   // First Rerun
    467  1.1  kamil   CBSetupAndRun();
    468  1.1  kamil   if (TPC.UpdateUnstableCounters(Options.HandleUnstable)) {
    469  1.1  kamil     // Second Rerun
    470  1.1  kamil     CBSetupAndRun();
    471  1.1  kamil     TPC.UpdateAndApplyUnstableCounters(Options.HandleUnstable);
    472  1.1  kamil   }
    473  1.1  kamil }
    474  1.1  kamil 
    475  1.1  kamil bool Fuzzer::RunOne(const uint8_t *Data, size_t Size, bool MayDeleteFile,
    476  1.1  kamil                     InputInfo *II, bool *FoundUniqFeatures) {
    477  1.1  kamil   if (!Size)
    478  1.1  kamil     return false;
    479  1.1  kamil 
    480  1.1  kamil   ExecuteCallback(Data, Size);
    481  1.1  kamil 
    482  1.1  kamil   UniqFeatureSetTmp.clear();
    483  1.1  kamil   size_t FoundUniqFeaturesOfII = 0;
    484  1.1  kamil   size_t NumUpdatesBefore = Corpus.NumFeatureUpdates();
    485  1.1  kamil   bool NewFeaturesUnstable = false;
    486  1.1  kamil 
    487  1.1  kamil   if (Options.HandleUnstable || Options.PrintUnstableStats) {
    488  1.1  kamil     TPC.CollectFeatures([&](size_t Feature) {
    489  1.1  kamil       if (Corpus.IsFeatureNew(Feature, Size, Options.Shrink))
    490  1.1  kamil         NewFeaturesUnstable = true;
    491  1.1  kamil     });
    492  1.1  kamil     if (NewFeaturesUnstable)
    493  1.1  kamil       CheckForUnstableCounters(Data, Size);
    494  1.1  kamil   }
    495  1.1  kamil 
    496  1.1  kamil   TPC.CollectFeatures([&](size_t Feature) {
    497  1.1  kamil     if (Corpus.AddFeature(Feature, Size, Options.Shrink))
    498  1.1  kamil       UniqFeatureSetTmp.push_back(Feature);
    499  1.1  kamil     if (Options.ReduceInputs && II)
    500  1.1  kamil       if (std::binary_search(II->UniqFeatureSet.begin(),
    501  1.1  kamil                              II->UniqFeatureSet.end(), Feature))
    502  1.1  kamil         FoundUniqFeaturesOfII++;
    503  1.1  kamil   });
    504  1.1  kamil 
    505  1.1  kamil   if (FoundUniqFeatures)
    506  1.1  kamil     *FoundUniqFeatures = FoundUniqFeaturesOfII;
    507  1.1  kamil   PrintPulseAndReportSlowInput(Data, Size);
    508  1.1  kamil   size_t NumNewFeatures = Corpus.NumFeatureUpdates() - NumUpdatesBefore;
    509  1.1  kamil 
    510  1.1  kamil   if (NumNewFeatures) {
    511  1.1  kamil     TPC.UpdateObservedPCs();
    512  1.1  kamil     Corpus.AddToCorpus({Data, Data + Size}, NumNewFeatures, MayDeleteFile,
    513  1.1  kamil                        TPC.ObservedFocusFunction(), UniqFeatureSetTmp, DFT, II);
    514  1.1  kamil     return true;
    515  1.1  kamil   }
    516  1.1  kamil   if (II && FoundUniqFeaturesOfII &&
    517  1.1  kamil       II->DataFlowTraceForFocusFunction.empty() &&
    518  1.1  kamil       FoundUniqFeaturesOfII == II->UniqFeatureSet.size() &&
    519  1.1  kamil       II->U.size() > Size) {
    520  1.1  kamil     Corpus.Replace(II, {Data, Data + Size});
    521  1.1  kamil     return true;
    522  1.1  kamil   }
    523  1.1  kamil   return false;
    524  1.1  kamil }
    525  1.1  kamil 
    526  1.1  kamil size_t Fuzzer::GetCurrentUnitInFuzzingThead(const uint8_t **Data) const {
    527  1.1  kamil   assert(InFuzzingThread());
    528  1.1  kamil   *Data = CurrentUnitData;
    529  1.1  kamil   return CurrentUnitSize;
    530  1.1  kamil }
    531  1.1  kamil 
    532  1.1  kamil void Fuzzer::CrashOnOverwrittenData() {
    533  1.1  kamil   Printf("==%d== ERROR: libFuzzer: fuzz target overwrites it's const input\n",
    534  1.1  kamil          GetPid());
    535  1.1  kamil   DumpCurrentUnit("crash-");
    536  1.1  kamil   Printf("SUMMARY: libFuzzer: out-of-memory\n");
    537  1.1  kamil   _Exit(Options.ErrorExitCode); // Stop right now.
    538  1.1  kamil }
    539  1.1  kamil 
    540  1.1  kamil // Compare two arrays, but not all bytes if the arrays are large.
    541  1.1  kamil static bool LooseMemeq(const uint8_t *A, const uint8_t *B, size_t Size) {
    542  1.1  kamil   const size_t Limit = 64;
    543  1.1  kamil   if (Size <= 64)
    544  1.1  kamil     return !memcmp(A, B, Size);
    545  1.1  kamil   // Compare first and last Limit/2 bytes.
    546  1.1  kamil   return !memcmp(A, B, Limit / 2) &&
    547  1.1  kamil          !memcmp(A + Size - Limit / 2, B + Size - Limit / 2, Limit / 2);
    548  1.1  kamil }
    549  1.1  kamil 
    550  1.1  kamil void Fuzzer::ExecuteCallback(const uint8_t *Data, size_t Size) {
    551  1.1  kamil   TPC.RecordInitialStack();
    552  1.1  kamil   TotalNumberOfRuns++;
    553  1.1  kamil   assert(InFuzzingThread());
    554  1.1  kamil   if (SMR.IsClient())
    555  1.1  kamil     SMR.WriteByteArray(Data, Size);
    556  1.1  kamil   // We copy the contents of Unit into a separate heap buffer
    557  1.1  kamil   // so that we reliably find buffer overflows in it.
    558  1.1  kamil   uint8_t *DataCopy = new uint8_t[Size];
    559  1.1  kamil   memcpy(DataCopy, Data, Size);
    560  1.1  kamil   if (EF->__msan_unpoison)
    561  1.1  kamil     EF->__msan_unpoison(DataCopy, Size);
    562  1.1  kamil   if (CurrentUnitData && CurrentUnitData != Data)
    563  1.1  kamil     memcpy(CurrentUnitData, Data, Size);
    564  1.1  kamil   CurrentUnitSize = Size;
    565  1.1  kamil   {
    566  1.1  kamil     ScopedEnableMsanInterceptorChecks S;
    567  1.1  kamil     AllocTracer.Start(Options.TraceMalloc);
    568  1.1  kamil     UnitStartTime = system_clock::now();
    569  1.1  kamil     TPC.ResetMaps();
    570  1.1  kamil     RunningUserCallback = true;
    571  1.1  kamil     int Res = CB(DataCopy, Size);
    572  1.1  kamil     RunningUserCallback = false;
    573  1.1  kamil     UnitStopTime = system_clock::now();
    574  1.1  kamil     (void)Res;
    575  1.1  kamil     assert(Res == 0);
    576  1.1  kamil     HasMoreMallocsThanFrees = AllocTracer.Stop();
    577  1.1  kamil   }
    578  1.1  kamil   if (!LooseMemeq(DataCopy, Data, Size))
    579  1.1  kamil     CrashOnOverwrittenData();
    580  1.1  kamil   CurrentUnitSize = 0;
    581  1.1  kamil   delete[] DataCopy;
    582  1.1  kamil }
    583  1.1  kamil 
    584  1.1  kamil void Fuzzer::WriteToOutputCorpus(const Unit &U) {
    585  1.1  kamil   if (Options.OnlyASCII)
    586  1.1  kamil     assert(IsASCII(U));
    587  1.1  kamil   if (Options.OutputCorpus.empty())
    588  1.1  kamil     return;
    589  1.1  kamil   std::string Path = DirPlusFile(Options.OutputCorpus, Hash(U));
    590  1.1  kamil   WriteToFile(U, Path);
    591  1.1  kamil   if (Options.Verbosity >= 2)
    592  1.1  kamil     Printf("Written %zd bytes to %s\n", U.size(), Path.c_str());
    593  1.1  kamil }
    594  1.1  kamil 
    595  1.1  kamil void Fuzzer::WriteUnitToFileWithPrefix(const Unit &U, const char *Prefix) {
    596  1.1  kamil   if (!Options.SaveArtifacts)
    597  1.1  kamil     return;
    598  1.1  kamil   std::string Path = Options.ArtifactPrefix + Prefix + Hash(U);
    599  1.1  kamil   if (!Options.ExactArtifactPath.empty())
    600  1.1  kamil     Path = Options.ExactArtifactPath; // Overrides ArtifactPrefix.
    601  1.1  kamil   WriteToFile(U, Path);
    602  1.1  kamil   Printf("artifact_prefix='%s'; Test unit written to %s\n",
    603  1.1  kamil          Options.ArtifactPrefix.c_str(), Path.c_str());
    604  1.1  kamil   if (U.size() <= kMaxUnitSizeToPrint)
    605  1.1  kamil     Printf("Base64: %s\n", Base64(U).c_str());
    606  1.1  kamil }
    607  1.1  kamil 
    608  1.1  kamil void Fuzzer::PrintStatusForNewUnit(const Unit &U, const char *Text) {
    609  1.1  kamil   if (!Options.PrintNEW)
    610  1.1  kamil     return;
    611  1.1  kamil   PrintStats(Text, "");
    612  1.1  kamil   if (Options.Verbosity) {
    613  1.1  kamil     Printf(" L: %zd/%zd ", U.size(), Corpus.MaxInputSize());
    614  1.1  kamil     MD.PrintMutationSequence();
    615  1.1  kamil     Printf("\n");
    616  1.1  kamil   }
    617  1.1  kamil }
    618  1.1  kamil 
    619  1.1  kamil void Fuzzer::ReportNewCoverage(InputInfo *II, const Unit &U) {
    620  1.1  kamil   II->NumSuccessfullMutations++;
    621  1.1  kamil   MD.RecordSuccessfulMutationSequence();
    622  1.1  kamil   PrintStatusForNewUnit(U, II->Reduced ? "REDUCE" : "NEW   ");
    623  1.1  kamil   WriteToOutputCorpus(U);
    624  1.1  kamil   NumberOfNewUnitsAdded++;
    625  1.1  kamil   CheckExitOnSrcPosOrItem(); // Check only after the unit is saved to corpus.
    626  1.1  kamil   LastCorpusUpdateRun = TotalNumberOfRuns;
    627  1.1  kamil }
    628  1.1  kamil 
    629  1.1  kamil // Tries detecting a memory leak on the particular input that we have just
    630  1.1  kamil // executed before calling this function.
    631  1.1  kamil void Fuzzer::TryDetectingAMemoryLeak(const uint8_t *Data, size_t Size,
    632  1.1  kamil                                      bool DuringInitialCorpusExecution) {
    633  1.1  kamil   if (!HasMoreMallocsThanFrees)
    634  1.1  kamil     return; // mallocs==frees, a leak is unlikely.
    635  1.1  kamil   if (!Options.DetectLeaks)
    636  1.1  kamil     return;
    637  1.1  kamil   if (!DuringInitialCorpusExecution &&
    638  1.1  kamil       TotalNumberOfRuns >= Options.MaxNumberOfRuns)
    639  1.1  kamil     return;
    640  1.1  kamil   if (!&(EF->__lsan_enable) || !&(EF->__lsan_disable) ||
    641  1.1  kamil       !(EF->__lsan_do_recoverable_leak_check))
    642  1.1  kamil     return; // No lsan.
    643  1.1  kamil   // Run the target once again, but with lsan disabled so that if there is
    644  1.1  kamil   // a real leak we do not report it twice.
    645  1.1  kamil   EF->__lsan_disable();
    646  1.1  kamil   ExecuteCallback(Data, Size);
    647  1.1  kamil   EF->__lsan_enable();
    648  1.1  kamil   if (!HasMoreMallocsThanFrees)
    649  1.1  kamil     return; // a leak is unlikely.
    650  1.1  kamil   if (NumberOfLeakDetectionAttempts++ > 1000) {
    651  1.1  kamil     Options.DetectLeaks = false;
    652  1.1  kamil     Printf("INFO: libFuzzer disabled leak detection after every mutation.\n"
    653  1.1  kamil            "      Most likely the target function accumulates allocated\n"
    654  1.1  kamil            "      memory in a global state w/o actually leaking it.\n"
    655  1.1  kamil            "      You may try running this binary with -trace_malloc=[12]"
    656  1.1  kamil            "      to get a trace of mallocs and frees.\n"
    657  1.1  kamil            "      If LeakSanitizer is enabled in this process it will still\n"
    658  1.1  kamil            "      run on the process shutdown.\n");
    659  1.1  kamil     return;
    660  1.1  kamil   }
    661  1.1  kamil   // Now perform the actual lsan pass. This is expensive and we must ensure
    662  1.1  kamil   // we don't call it too often.
    663  1.1  kamil   if (EF->__lsan_do_recoverable_leak_check()) { // Leak is found, report it.
    664  1.1  kamil     if (DuringInitialCorpusExecution)
    665  1.1  kamil       Printf("\nINFO: a leak has been found in the initial corpus.\n\n");
    666  1.1  kamil     Printf("INFO: to ignore leaks on libFuzzer side use -detect_leaks=0.\n\n");
    667  1.1  kamil     CurrentUnitSize = Size;
    668  1.1  kamil     DumpCurrentUnit("leak-");
    669  1.1  kamil     PrintFinalStats();
    670  1.1  kamil     _Exit(Options.ErrorExitCode); // not exit() to disable lsan further on.
    671  1.1  kamil   }
    672  1.1  kamil }
    673  1.1  kamil 
    674  1.1  kamil void Fuzzer::MutateAndTestOne() {
    675  1.1  kamil   MD.StartMutationSequence();
    676  1.1  kamil 
    677  1.1  kamil   auto &II = Corpus.ChooseUnitToMutate(MD.GetRand());
    678  1.1  kamil   const auto &U = II.U;
    679  1.1  kamil   memcpy(BaseSha1, II.Sha1, sizeof(BaseSha1));
    680  1.1  kamil   assert(CurrentUnitData);
    681  1.1  kamil   size_t Size = U.size();
    682  1.1  kamil   assert(Size <= MaxInputLen && "Oversized Unit");
    683  1.1  kamil   memcpy(CurrentUnitData, U.data(), Size);
    684  1.1  kamil 
    685  1.1  kamil   assert(MaxMutationLen > 0);
    686  1.1  kamil 
    687  1.1  kamil   size_t CurrentMaxMutationLen =
    688  1.1  kamil       Min(MaxMutationLen, Max(U.size(), TmpMaxMutationLen));
    689  1.1  kamil   assert(CurrentMaxMutationLen > 0);
    690  1.1  kamil 
    691  1.1  kamil   for (int i = 0; i < Options.MutateDepth; i++) {
    692  1.1  kamil     if (TotalNumberOfRuns >= Options.MaxNumberOfRuns)
    693  1.1  kamil       break;
    694  1.1  kamil     MaybeExitGracefully();
    695  1.1  kamil     size_t NewSize = 0;
    696  1.1  kamil     if (II.HasFocusFunction && !II.DataFlowTraceForFocusFunction.empty() &&
    697  1.1  kamil         Size <= CurrentMaxMutationLen)
    698  1.1  kamil       NewSize = MD.MutateWithMask(CurrentUnitData, Size, Size,
    699  1.1  kamil                                   II.DataFlowTraceForFocusFunction);
    700  1.1  kamil     else
    701  1.1  kamil       NewSize = MD.Mutate(CurrentUnitData, Size, CurrentMaxMutationLen);
    702  1.1  kamil     assert(NewSize > 0 && "Mutator returned empty unit");
    703  1.1  kamil     assert(NewSize <= CurrentMaxMutationLen && "Mutator return oversized unit");
    704  1.1  kamil     Size = NewSize;
    705  1.1  kamil     II.NumExecutedMutations++;
    706  1.1  kamil 
    707  1.1  kamil     bool FoundUniqFeatures = false;
    708  1.1  kamil     bool NewCov = RunOne(CurrentUnitData, Size, /*MayDeleteFile=*/true, &II,
    709  1.1  kamil                          &FoundUniqFeatures);
    710  1.1  kamil     TryDetectingAMemoryLeak(CurrentUnitData, Size,
    711  1.1  kamil                             /*DuringInitialCorpusExecution*/ false);
    712  1.1  kamil     if (NewCov) {
    713  1.1  kamil       ReportNewCoverage(&II, {CurrentUnitData, CurrentUnitData + Size});
    714  1.1  kamil       break;  // We will mutate this input more in the next rounds.
    715  1.1  kamil     }
    716  1.1  kamil     if (Options.ReduceDepth && !FoundUniqFeatures)
    717  1.1  kamil         break;
    718  1.1  kamil   }
    719  1.1  kamil }
    720  1.1  kamil 
    721  1.1  kamil void Fuzzer::PurgeAllocator() {
    722  1.1  kamil   if (Options.PurgeAllocatorIntervalSec < 0 || !EF->__sanitizer_purge_allocator)
    723  1.1  kamil     return;
    724  1.1  kamil   if (duration_cast<seconds>(system_clock::now() -
    725  1.1  kamil                              LastAllocatorPurgeAttemptTime)
    726  1.1  kamil           .count() < Options.PurgeAllocatorIntervalSec)
    727  1.1  kamil     return;
    728  1.1  kamil 
    729  1.1  kamil   if (Options.RssLimitMb <= 0 ||
    730  1.1  kamil       GetPeakRSSMb() > static_cast<size_t>(Options.RssLimitMb) / 2)
    731  1.1  kamil     EF->__sanitizer_purge_allocator();
    732  1.1  kamil 
    733  1.1  kamil   LastAllocatorPurgeAttemptTime = system_clock::now();
    734  1.1  kamil }
    735  1.1  kamil 
    736  1.1  kamil void Fuzzer::ReadAndExecuteSeedCorpora(const Vector<std::string> &CorpusDirs) {
    737  1.1  kamil   const size_t kMaxSaneLen = 1 << 20;
    738  1.1  kamil   const size_t kMinDefaultLen = 4096;
    739  1.1  kamil   Vector<SizedFile> SizedFiles;
    740  1.1  kamil   size_t MaxSize = 0;
    741  1.1  kamil   size_t MinSize = -1;
    742  1.1  kamil   size_t TotalSize = 0;
    743  1.1  kamil   size_t LastNumFiles = 0;
    744  1.1  kamil   for (auto &Dir : CorpusDirs) {
    745  1.1  kamil     GetSizedFilesFromDir(Dir, &SizedFiles);
    746  1.1  kamil     Printf("INFO: % 8zd files found in %s\n", SizedFiles.size() - LastNumFiles,
    747  1.1  kamil            Dir.c_str());
    748  1.1  kamil     LastNumFiles = SizedFiles.size();
    749  1.1  kamil   }
    750  1.1  kamil   for (auto &File : SizedFiles) {
    751  1.1  kamil     MaxSize = Max(File.Size, MaxSize);
    752  1.1  kamil     MinSize = Min(File.Size, MinSize);
    753  1.1  kamil     TotalSize += File.Size;
    754  1.1  kamil   }
    755  1.1  kamil   if (Options.MaxLen == 0)
    756  1.1  kamil     SetMaxInputLen(std::min(std::max(kMinDefaultLen, MaxSize), kMaxSaneLen));
    757  1.1  kamil   assert(MaxInputLen > 0);
    758  1.1  kamil 
    759  1.1  kamil   // Test the callback with empty input and never try it again.
    760  1.1  kamil   uint8_t dummy = 0;
    761  1.1  kamil   ExecuteCallback(&dummy, 0);
    762  1.1  kamil 
    763  1.1  kamil   if (SizedFiles.empty()) {
    764  1.1  kamil     Printf("INFO: A corpus is not provided, starting from an empty corpus\n");
    765  1.1  kamil     Unit U({'\n'}); // Valid ASCII input.
    766  1.1  kamil     RunOne(U.data(), U.size());
    767  1.1  kamil   } else {
    768  1.1  kamil     Printf("INFO: seed corpus: files: %zd min: %zdb max: %zdb total: %zdb"
    769  1.1  kamil            " rss: %zdMb\n",
    770  1.1  kamil            SizedFiles.size(), MinSize, MaxSize, TotalSize, GetPeakRSSMb());
    771  1.1  kamil     if (Options.ShuffleAtStartUp)
    772  1.1  kamil       std::shuffle(SizedFiles.begin(), SizedFiles.end(), MD.GetRand());
    773  1.1  kamil 
    774  1.1  kamil     if (Options.PreferSmall) {
    775  1.1  kamil       std::stable_sort(SizedFiles.begin(), SizedFiles.end());
    776  1.1  kamil       assert(SizedFiles.front().Size <= SizedFiles.back().Size);
    777  1.1  kamil     }
    778  1.1  kamil 
    779  1.1  kamil     // Load and execute inputs one by one.
    780  1.1  kamil     for (auto &SF : SizedFiles) {
    781  1.1  kamil       auto U = FileToVector(SF.File, MaxInputLen, /*ExitOnError=*/false);
    782  1.1  kamil       assert(U.size() <= MaxInputLen);
    783  1.1  kamil       RunOne(U.data(), U.size());
    784  1.1  kamil       CheckExitOnSrcPosOrItem();
    785  1.1  kamil       TryDetectingAMemoryLeak(U.data(), U.size(),
    786  1.1  kamil                               /*DuringInitialCorpusExecution*/ true);
    787  1.1  kamil     }
    788  1.1  kamil   }
    789  1.1  kamil 
    790  1.1  kamil   PrintStats("INITED");
    791  1.1  kamil   if (!Options.FocusFunction.empty())
    792  1.1  kamil     Printf("INFO: %zd/%zd inputs touch the focus function\n",
    793  1.1  kamil            Corpus.NumInputsThatTouchFocusFunction(), Corpus.size());
    794  1.1  kamil   if (!Options.DataFlowTrace.empty())
    795  1.1  kamil     Printf("INFO: %zd/%zd inputs have the Data Flow Trace\n",
    796  1.1  kamil            Corpus.NumInputsWithDataFlowTrace(), Corpus.size());
    797  1.1  kamil 
    798  1.1  kamil   if (Corpus.empty() && Options.MaxNumberOfRuns) {
    799  1.1  kamil     Printf("ERROR: no interesting inputs were found. "
    800  1.1  kamil            "Is the code instrumented for coverage? Exiting.\n");
    801  1.1  kamil     exit(1);
    802  1.1  kamil   }
    803  1.1  kamil }
    804  1.1  kamil 
    805  1.1  kamil void Fuzzer::Loop(const Vector<std::string> &CorpusDirs) {
    806  1.1  kamil   ReadAndExecuteSeedCorpora(CorpusDirs);
    807  1.1  kamil   DFT.Clear();  // No need for DFT any more.
    808  1.1  kamil   TPC.SetPrintNewPCs(Options.PrintNewCovPcs);
    809  1.1  kamil   TPC.SetPrintNewFuncs(Options.PrintNewCovFuncs);
    810  1.1  kamil   system_clock::time_point LastCorpusReload = system_clock::now();
    811  1.1  kamil   if (Options.DoCrossOver)
    812  1.1  kamil     MD.SetCorpus(&Corpus);
    813  1.1  kamil   while (true) {
    814  1.1  kamil     auto Now = system_clock::now();
    815  1.1  kamil     if (duration_cast<seconds>(Now - LastCorpusReload).count() >=
    816  1.1  kamil         Options.ReloadIntervalSec) {
    817  1.1  kamil       RereadOutputCorpus(MaxInputLen);
    818  1.1  kamil       LastCorpusReload = system_clock::now();
    819  1.1  kamil     }
    820  1.1  kamil     if (TotalNumberOfRuns >= Options.MaxNumberOfRuns)
    821  1.1  kamil       break;
    822  1.1  kamil     if (TimedOut())
    823  1.1  kamil       break;
    824  1.1  kamil 
    825  1.1  kamil     // Update TmpMaxMutationLen
    826  1.1  kamil     if (Options.LenControl) {
    827  1.1  kamil       if (TmpMaxMutationLen < MaxMutationLen &&
    828  1.1  kamil           TotalNumberOfRuns - LastCorpusUpdateRun >
    829  1.1  kamil               Options.LenControl * Log(TmpMaxMutationLen)) {
    830  1.1  kamil         TmpMaxMutationLen =
    831  1.1  kamil             Min(MaxMutationLen, TmpMaxMutationLen + Log(TmpMaxMutationLen));
    832  1.1  kamil         LastCorpusUpdateRun = TotalNumberOfRuns;
    833  1.1  kamil       }
    834  1.1  kamil     } else {
    835  1.1  kamil       TmpMaxMutationLen = MaxMutationLen;
    836  1.1  kamil     }
    837  1.1  kamil 
    838  1.1  kamil     // Perform several mutations and runs.
    839  1.1  kamil     MutateAndTestOne();
    840  1.1  kamil 
    841  1.1  kamil     PurgeAllocator();
    842  1.1  kamil   }
    843  1.1  kamil 
    844  1.1  kamil   PrintStats("DONE  ", "\n");
    845  1.1  kamil   MD.PrintRecommendedDictionary();
    846  1.1  kamil }
    847  1.1  kamil 
    848  1.1  kamil void Fuzzer::MinimizeCrashLoop(const Unit &U) {
    849  1.1  kamil   if (U.size() <= 1)
    850  1.1  kamil     return;
    851  1.1  kamil   while (!TimedOut() && TotalNumberOfRuns < Options.MaxNumberOfRuns) {
    852  1.1  kamil     MD.StartMutationSequence();
    853  1.1  kamil     memcpy(CurrentUnitData, U.data(), U.size());
    854  1.1  kamil     for (int i = 0; i < Options.MutateDepth; i++) {
    855  1.1  kamil       size_t NewSize = MD.Mutate(CurrentUnitData, U.size(), MaxMutationLen);
    856  1.1  kamil       assert(NewSize > 0 && NewSize <= MaxMutationLen);
    857  1.1  kamil       ExecuteCallback(CurrentUnitData, NewSize);
    858  1.1  kamil       PrintPulseAndReportSlowInput(CurrentUnitData, NewSize);
    859  1.1  kamil       TryDetectingAMemoryLeak(CurrentUnitData, NewSize,
    860  1.1  kamil                               /*DuringInitialCorpusExecution*/ false);
    861  1.1  kamil     }
    862  1.1  kamil   }
    863  1.1  kamil }
    864  1.1  kamil 
    865  1.1  kamil void Fuzzer::AnnounceOutput(const uint8_t *Data, size_t Size) {
    866  1.1  kamil   if (SMR.IsServer()) {
    867  1.1  kamil     SMR.WriteByteArray(Data, Size);
    868  1.1  kamil   } else if (SMR.IsClient()) {
    869  1.1  kamil     SMR.PostClient();
    870  1.1  kamil     SMR.WaitServer();
    871  1.1  kamil     size_t OtherSize = SMR.ReadByteArraySize();
    872  1.1  kamil     uint8_t *OtherData = SMR.GetByteArray();
    873  1.1  kamil     if (Size != OtherSize || memcmp(Data, OtherData, Size) != 0) {
    874  1.1  kamil       size_t i = 0;
    875  1.1  kamil       for (i = 0; i < Min(Size, OtherSize); i++)
    876  1.1  kamil         if (Data[i] != OtherData[i])
    877  1.1  kamil           break;
    878  1.1  kamil       Printf("==%lu== ERROR: libFuzzer: equivalence-mismatch. Sizes: %zd %zd; "
    879  1.1  kamil              "offset %zd\n",
    880  1.1  kamil              GetPid(), Size, OtherSize, i);
    881  1.1  kamil       DumpCurrentUnit("mismatch-");
    882  1.1  kamil       Printf("SUMMARY: libFuzzer: equivalence-mismatch\n");
    883  1.1  kamil       PrintFinalStats();
    884  1.1  kamil       _Exit(Options.ErrorExitCode);
    885  1.1  kamil     }
    886  1.1  kamil   }
    887  1.1  kamil }
    888  1.1  kamil 
    889  1.1  kamil } // namespace fuzzer
    890  1.1  kamil 
    891  1.1  kamil extern "C" {
    892  1.1  kamil 
    893  1.1  kamil __attribute__((visibility("default"))) size_t
    894  1.1  kamil LLVMFuzzerMutate(uint8_t *Data, size_t Size, size_t MaxSize) {
    895  1.1  kamil   assert(fuzzer::F);
    896  1.1  kamil   return fuzzer::F->GetMD().DefaultMutate(Data, Size, MaxSize);
    897  1.1  kamil }
    898  1.1  kamil 
    899  1.1  kamil // Experimental
    900  1.1  kamil __attribute__((visibility("default"))) void
    901  1.1  kamil LLVMFuzzerAnnounceOutput(const uint8_t *Data, size_t Size) {
    902  1.1  kamil   assert(fuzzer::F);
    903  1.1  kamil   fuzzer::F->AnnounceOutput(Data, Size);
    904  1.1  kamil }
    905  1.1  kamil } // extern "C"
    906