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