10b57cec5SDimitry Andric //===- FuzzerLoop.cpp - Fuzzer's main loop --------------------------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // Fuzzer's main loop. 90b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 100b57cec5SDimitry Andric 110b57cec5SDimitry Andric #include "FuzzerCorpus.h" 120b57cec5SDimitry Andric #include "FuzzerIO.h" 130b57cec5SDimitry Andric #include "FuzzerInternal.h" 140b57cec5SDimitry Andric #include "FuzzerMutate.h" 15*5ffd83dbSDimitry Andric #include "FuzzerPlatform.h" 160b57cec5SDimitry Andric #include "FuzzerRandom.h" 170b57cec5SDimitry Andric #include "FuzzerTracePC.h" 180b57cec5SDimitry Andric #include <algorithm> 190b57cec5SDimitry Andric #include <cstring> 200b57cec5SDimitry Andric #include <memory> 210b57cec5SDimitry Andric #include <mutex> 220b57cec5SDimitry Andric #include <set> 230b57cec5SDimitry Andric 240b57cec5SDimitry Andric #if defined(__has_include) 250b57cec5SDimitry Andric #if __has_include(<sanitizer / lsan_interface.h>) 260b57cec5SDimitry Andric #include <sanitizer/lsan_interface.h> 270b57cec5SDimitry Andric #endif 280b57cec5SDimitry Andric #endif 290b57cec5SDimitry Andric 300b57cec5SDimitry Andric #define NO_SANITIZE_MEMORY 310b57cec5SDimitry Andric #if defined(__has_feature) 320b57cec5SDimitry Andric #if __has_feature(memory_sanitizer) 330b57cec5SDimitry Andric #undef NO_SANITIZE_MEMORY 340b57cec5SDimitry Andric #define NO_SANITIZE_MEMORY __attribute__((no_sanitize_memory)) 350b57cec5SDimitry Andric #endif 360b57cec5SDimitry Andric #endif 370b57cec5SDimitry Andric 380b57cec5SDimitry Andric namespace fuzzer { 390b57cec5SDimitry Andric static const size_t kMaxUnitSizeToPrint = 256; 400b57cec5SDimitry Andric 410b57cec5SDimitry Andric thread_local bool Fuzzer::IsMyThread; 420b57cec5SDimitry Andric 430b57cec5SDimitry Andric bool RunningUserCallback = false; 440b57cec5SDimitry Andric 450b57cec5SDimitry Andric // Only one Fuzzer per process. 460b57cec5SDimitry Andric static Fuzzer *F; 470b57cec5SDimitry Andric 480b57cec5SDimitry Andric // Leak detection is expensive, so we first check if there were more mallocs 490b57cec5SDimitry Andric // than frees (using the sanitizer malloc hooks) and only then try to call lsan. 500b57cec5SDimitry Andric struct MallocFreeTracer { 510b57cec5SDimitry Andric void Start(int TraceLevel) { 520b57cec5SDimitry Andric this->TraceLevel = TraceLevel; 530b57cec5SDimitry Andric if (TraceLevel) 540b57cec5SDimitry Andric Printf("MallocFreeTracer: START\n"); 550b57cec5SDimitry Andric Mallocs = 0; 560b57cec5SDimitry Andric Frees = 0; 570b57cec5SDimitry Andric } 580b57cec5SDimitry Andric // Returns true if there were more mallocs than frees. 590b57cec5SDimitry Andric bool Stop() { 600b57cec5SDimitry Andric if (TraceLevel) 610b57cec5SDimitry Andric Printf("MallocFreeTracer: STOP %zd %zd (%s)\n", Mallocs.load(), 620b57cec5SDimitry Andric Frees.load(), Mallocs == Frees ? "same" : "DIFFERENT"); 630b57cec5SDimitry Andric bool Result = Mallocs > Frees; 640b57cec5SDimitry Andric Mallocs = 0; 650b57cec5SDimitry Andric Frees = 0; 660b57cec5SDimitry Andric TraceLevel = 0; 670b57cec5SDimitry Andric return Result; 680b57cec5SDimitry Andric } 690b57cec5SDimitry Andric std::atomic<size_t> Mallocs; 700b57cec5SDimitry Andric std::atomic<size_t> Frees; 710b57cec5SDimitry Andric int TraceLevel = 0; 720b57cec5SDimitry Andric 730b57cec5SDimitry Andric std::recursive_mutex TraceMutex; 740b57cec5SDimitry Andric bool TraceDisabled = false; 750b57cec5SDimitry Andric }; 760b57cec5SDimitry Andric 770b57cec5SDimitry Andric static MallocFreeTracer AllocTracer; 780b57cec5SDimitry Andric 790b57cec5SDimitry Andric // Locks printing and avoids nested hooks triggered from mallocs/frees in 800b57cec5SDimitry Andric // sanitizer. 810b57cec5SDimitry Andric class TraceLock { 820b57cec5SDimitry Andric public: 830b57cec5SDimitry Andric TraceLock() : Lock(AllocTracer.TraceMutex) { 840b57cec5SDimitry Andric AllocTracer.TraceDisabled = !AllocTracer.TraceDisabled; 850b57cec5SDimitry Andric } 860b57cec5SDimitry Andric ~TraceLock() { AllocTracer.TraceDisabled = !AllocTracer.TraceDisabled; } 870b57cec5SDimitry Andric 880b57cec5SDimitry Andric bool IsDisabled() const { 890b57cec5SDimitry Andric // This is already inverted value. 900b57cec5SDimitry Andric return !AllocTracer.TraceDisabled; 910b57cec5SDimitry Andric } 920b57cec5SDimitry Andric 930b57cec5SDimitry Andric private: 940b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> Lock; 950b57cec5SDimitry Andric }; 960b57cec5SDimitry Andric 970b57cec5SDimitry Andric ATTRIBUTE_NO_SANITIZE_MEMORY 980b57cec5SDimitry Andric void MallocHook(const volatile void *ptr, size_t size) { 990b57cec5SDimitry Andric size_t N = AllocTracer.Mallocs++; 1000b57cec5SDimitry Andric F->HandleMalloc(size); 1010b57cec5SDimitry Andric if (int TraceLevel = AllocTracer.TraceLevel) { 1020b57cec5SDimitry Andric TraceLock Lock; 1030b57cec5SDimitry Andric if (Lock.IsDisabled()) 1040b57cec5SDimitry Andric return; 1050b57cec5SDimitry Andric Printf("MALLOC[%zd] %p %zd\n", N, ptr, size); 1060b57cec5SDimitry Andric if (TraceLevel >= 2 && EF) 1070b57cec5SDimitry Andric PrintStackTrace(); 1080b57cec5SDimitry Andric } 1090b57cec5SDimitry Andric } 1100b57cec5SDimitry Andric 1110b57cec5SDimitry Andric ATTRIBUTE_NO_SANITIZE_MEMORY 1120b57cec5SDimitry Andric void FreeHook(const volatile void *ptr) { 1130b57cec5SDimitry Andric size_t N = AllocTracer.Frees++; 1140b57cec5SDimitry Andric if (int TraceLevel = AllocTracer.TraceLevel) { 1150b57cec5SDimitry Andric TraceLock Lock; 1160b57cec5SDimitry Andric if (Lock.IsDisabled()) 1170b57cec5SDimitry Andric return; 1180b57cec5SDimitry Andric Printf("FREE[%zd] %p\n", N, ptr); 1190b57cec5SDimitry Andric if (TraceLevel >= 2 && EF) 1200b57cec5SDimitry Andric PrintStackTrace(); 1210b57cec5SDimitry Andric } 1220b57cec5SDimitry Andric } 1230b57cec5SDimitry Andric 1240b57cec5SDimitry Andric // Crash on a single malloc that exceeds the rss limit. 1250b57cec5SDimitry Andric void Fuzzer::HandleMalloc(size_t Size) { 1260b57cec5SDimitry Andric if (!Options.MallocLimitMb || (Size >> 20) < (size_t)Options.MallocLimitMb) 1270b57cec5SDimitry Andric return; 1280b57cec5SDimitry Andric Printf("==%d== ERROR: libFuzzer: out-of-memory (malloc(%zd))\n", GetPid(), 1290b57cec5SDimitry Andric Size); 1300b57cec5SDimitry Andric Printf(" To change the out-of-memory limit use -rss_limit_mb=<N>\n\n"); 1310b57cec5SDimitry Andric PrintStackTrace(); 1320b57cec5SDimitry Andric DumpCurrentUnit("oom-"); 1330b57cec5SDimitry Andric Printf("SUMMARY: libFuzzer: out-of-memory\n"); 1340b57cec5SDimitry Andric PrintFinalStats(); 1350b57cec5SDimitry Andric _Exit(Options.OOMExitCode); // Stop right now. 1360b57cec5SDimitry Andric } 1370b57cec5SDimitry Andric 1380b57cec5SDimitry Andric Fuzzer::Fuzzer(UserCallback CB, InputCorpus &Corpus, MutationDispatcher &MD, 1390b57cec5SDimitry Andric FuzzingOptions Options) 1400b57cec5SDimitry Andric : CB(CB), Corpus(Corpus), MD(MD), Options(Options) { 1410b57cec5SDimitry Andric if (EF->__sanitizer_set_death_callback) 1420b57cec5SDimitry Andric EF->__sanitizer_set_death_callback(StaticDeathCallback); 1430b57cec5SDimitry Andric assert(!F); 1440b57cec5SDimitry Andric F = this; 1450b57cec5SDimitry Andric TPC.ResetMaps(); 1460b57cec5SDimitry Andric IsMyThread = true; 1470b57cec5SDimitry Andric if (Options.DetectLeaks && EF->__sanitizer_install_malloc_and_free_hooks) 1480b57cec5SDimitry Andric EF->__sanitizer_install_malloc_and_free_hooks(MallocHook, FreeHook); 1490b57cec5SDimitry Andric TPC.SetUseCounters(Options.UseCounters); 1500b57cec5SDimitry Andric TPC.SetUseValueProfileMask(Options.UseValueProfile); 1510b57cec5SDimitry Andric 1520b57cec5SDimitry Andric if (Options.Verbosity) 1530b57cec5SDimitry Andric TPC.PrintModuleInfo(); 1540b57cec5SDimitry Andric if (!Options.OutputCorpus.empty() && Options.ReloadIntervalSec) 1550b57cec5SDimitry Andric EpochOfLastReadOfOutputCorpus = GetEpoch(Options.OutputCorpus); 1560b57cec5SDimitry Andric MaxInputLen = MaxMutationLen = Options.MaxLen; 1570b57cec5SDimitry Andric TmpMaxMutationLen = 0; // Will be set once we load the corpus. 1580b57cec5SDimitry Andric AllocateCurrentUnitData(); 1590b57cec5SDimitry Andric CurrentUnitSize = 0; 1600b57cec5SDimitry Andric memset(BaseSha1, 0, sizeof(BaseSha1)); 1610b57cec5SDimitry Andric } 1620b57cec5SDimitry Andric 1630b57cec5SDimitry Andric Fuzzer::~Fuzzer() {} 1640b57cec5SDimitry Andric 1650b57cec5SDimitry Andric void Fuzzer::AllocateCurrentUnitData() { 1660b57cec5SDimitry Andric if (CurrentUnitData || MaxInputLen == 0) 1670b57cec5SDimitry Andric return; 1680b57cec5SDimitry Andric CurrentUnitData = new uint8_t[MaxInputLen]; 1690b57cec5SDimitry Andric } 1700b57cec5SDimitry Andric 1710b57cec5SDimitry Andric void Fuzzer::StaticDeathCallback() { 1720b57cec5SDimitry Andric assert(F); 1730b57cec5SDimitry Andric F->DeathCallback(); 1740b57cec5SDimitry Andric } 1750b57cec5SDimitry Andric 1760b57cec5SDimitry Andric void Fuzzer::DumpCurrentUnit(const char *Prefix) { 1770b57cec5SDimitry Andric if (!CurrentUnitData) 1780b57cec5SDimitry Andric return; // Happens when running individual inputs. 1790b57cec5SDimitry Andric ScopedDisableMsanInterceptorChecks S; 1800b57cec5SDimitry Andric MD.PrintMutationSequence(); 1810b57cec5SDimitry Andric Printf("; base unit: %s\n", Sha1ToString(BaseSha1).c_str()); 1820b57cec5SDimitry Andric size_t UnitSize = CurrentUnitSize; 1830b57cec5SDimitry Andric if (UnitSize <= kMaxUnitSizeToPrint) { 1840b57cec5SDimitry Andric PrintHexArray(CurrentUnitData, UnitSize, "\n"); 1850b57cec5SDimitry Andric PrintASCII(CurrentUnitData, UnitSize, "\n"); 1860b57cec5SDimitry Andric } 1870b57cec5SDimitry Andric WriteUnitToFileWithPrefix({CurrentUnitData, CurrentUnitData + UnitSize}, 1880b57cec5SDimitry Andric Prefix); 1890b57cec5SDimitry Andric } 1900b57cec5SDimitry Andric 1910b57cec5SDimitry Andric NO_SANITIZE_MEMORY 1920b57cec5SDimitry Andric void Fuzzer::DeathCallback() { 1930b57cec5SDimitry Andric DumpCurrentUnit("crash-"); 1940b57cec5SDimitry Andric PrintFinalStats(); 1950b57cec5SDimitry Andric } 1960b57cec5SDimitry Andric 1970b57cec5SDimitry Andric void Fuzzer::StaticAlarmCallback() { 1980b57cec5SDimitry Andric assert(F); 1990b57cec5SDimitry Andric F->AlarmCallback(); 2000b57cec5SDimitry Andric } 2010b57cec5SDimitry Andric 2020b57cec5SDimitry Andric void Fuzzer::StaticCrashSignalCallback() { 2030b57cec5SDimitry Andric assert(F); 2040b57cec5SDimitry Andric F->CrashCallback(); 2050b57cec5SDimitry Andric } 2060b57cec5SDimitry Andric 2070b57cec5SDimitry Andric void Fuzzer::StaticExitCallback() { 2080b57cec5SDimitry Andric assert(F); 2090b57cec5SDimitry Andric F->ExitCallback(); 2100b57cec5SDimitry Andric } 2110b57cec5SDimitry Andric 2120b57cec5SDimitry Andric void Fuzzer::StaticInterruptCallback() { 2130b57cec5SDimitry Andric assert(F); 2140b57cec5SDimitry Andric F->InterruptCallback(); 2150b57cec5SDimitry Andric } 2160b57cec5SDimitry Andric 2170b57cec5SDimitry Andric void Fuzzer::StaticGracefulExitCallback() { 2180b57cec5SDimitry Andric assert(F); 2190b57cec5SDimitry Andric F->GracefulExitRequested = true; 2200b57cec5SDimitry Andric Printf("INFO: signal received, trying to exit gracefully\n"); 2210b57cec5SDimitry Andric } 2220b57cec5SDimitry Andric 2230b57cec5SDimitry Andric void Fuzzer::StaticFileSizeExceedCallback() { 2240b57cec5SDimitry Andric Printf("==%lu== ERROR: libFuzzer: file size exceeded\n", GetPid()); 2250b57cec5SDimitry Andric exit(1); 2260b57cec5SDimitry Andric } 2270b57cec5SDimitry Andric 2280b57cec5SDimitry Andric void Fuzzer::CrashCallback() { 2290b57cec5SDimitry Andric if (EF->__sanitizer_acquire_crash_state && 2300b57cec5SDimitry Andric !EF->__sanitizer_acquire_crash_state()) 2310b57cec5SDimitry Andric return; 2320b57cec5SDimitry Andric Printf("==%lu== ERROR: libFuzzer: deadly signal\n", GetPid()); 2330b57cec5SDimitry Andric PrintStackTrace(); 2340b57cec5SDimitry Andric Printf("NOTE: libFuzzer has rudimentary signal handlers.\n" 2350b57cec5SDimitry Andric " Combine libFuzzer with AddressSanitizer or similar for better " 2360b57cec5SDimitry Andric "crash reports.\n"); 2370b57cec5SDimitry Andric Printf("SUMMARY: libFuzzer: deadly signal\n"); 2380b57cec5SDimitry Andric DumpCurrentUnit("crash-"); 2390b57cec5SDimitry Andric PrintFinalStats(); 2400b57cec5SDimitry Andric _Exit(Options.ErrorExitCode); // Stop right now. 2410b57cec5SDimitry Andric } 2420b57cec5SDimitry Andric 2430b57cec5SDimitry Andric void Fuzzer::ExitCallback() { 2440b57cec5SDimitry Andric if (!RunningUserCallback) 2450b57cec5SDimitry Andric return; // This exit did not come from the user callback 2460b57cec5SDimitry Andric if (EF->__sanitizer_acquire_crash_state && 2470b57cec5SDimitry Andric !EF->__sanitizer_acquire_crash_state()) 2480b57cec5SDimitry Andric return; 2490b57cec5SDimitry Andric Printf("==%lu== ERROR: libFuzzer: fuzz target exited\n", GetPid()); 2500b57cec5SDimitry Andric PrintStackTrace(); 2510b57cec5SDimitry Andric Printf("SUMMARY: libFuzzer: fuzz target exited\n"); 2520b57cec5SDimitry Andric DumpCurrentUnit("crash-"); 2530b57cec5SDimitry Andric PrintFinalStats(); 2540b57cec5SDimitry Andric _Exit(Options.ErrorExitCode); 2550b57cec5SDimitry Andric } 2560b57cec5SDimitry Andric 2570b57cec5SDimitry Andric void Fuzzer::MaybeExitGracefully() { 2580b57cec5SDimitry Andric if (!F->GracefulExitRequested) return; 2590b57cec5SDimitry Andric Printf("==%lu== INFO: libFuzzer: exiting as requested\n", GetPid()); 260*5ffd83dbSDimitry Andric RmDirRecursive(TempPath("FuzzWithFork", ".dir")); 2610b57cec5SDimitry Andric F->PrintFinalStats(); 2620b57cec5SDimitry Andric _Exit(0); 2630b57cec5SDimitry Andric } 2640b57cec5SDimitry Andric 2650b57cec5SDimitry Andric void Fuzzer::InterruptCallback() { 2660b57cec5SDimitry Andric Printf("==%lu== libFuzzer: run interrupted; exiting\n", GetPid()); 2670b57cec5SDimitry Andric PrintFinalStats(); 2680b57cec5SDimitry Andric ScopedDisableMsanInterceptorChecks S; // RmDirRecursive may call opendir(). 269*5ffd83dbSDimitry Andric RmDirRecursive(TempPath("FuzzWithFork", ".dir")); 2700b57cec5SDimitry Andric // Stop right now, don't perform any at-exit actions. 2710b57cec5SDimitry Andric _Exit(Options.InterruptExitCode); 2720b57cec5SDimitry Andric } 2730b57cec5SDimitry Andric 2740b57cec5SDimitry Andric NO_SANITIZE_MEMORY 2750b57cec5SDimitry Andric void Fuzzer::AlarmCallback() { 2760b57cec5SDimitry Andric assert(Options.UnitTimeoutSec > 0); 27768d75effSDimitry Andric // In Windows and Fuchsia, Alarm callback is executed by a different thread. 2780b57cec5SDimitry Andric // NetBSD's current behavior needs this change too. 27968d75effSDimitry Andric #if !LIBFUZZER_WINDOWS && !LIBFUZZER_NETBSD && !LIBFUZZER_FUCHSIA 2800b57cec5SDimitry Andric if (!InFuzzingThread()) 2810b57cec5SDimitry Andric return; 2820b57cec5SDimitry Andric #endif 2830b57cec5SDimitry Andric if (!RunningUserCallback) 2840b57cec5SDimitry Andric return; // We have not started running units yet. 2850b57cec5SDimitry Andric size_t Seconds = 2860b57cec5SDimitry Andric duration_cast<seconds>(system_clock::now() - UnitStartTime).count(); 2870b57cec5SDimitry Andric if (Seconds == 0) 2880b57cec5SDimitry Andric return; 2890b57cec5SDimitry Andric if (Options.Verbosity >= 2) 2900b57cec5SDimitry Andric Printf("AlarmCallback %zd\n", Seconds); 2910b57cec5SDimitry Andric if (Seconds >= (size_t)Options.UnitTimeoutSec) { 2920b57cec5SDimitry Andric if (EF->__sanitizer_acquire_crash_state && 2930b57cec5SDimitry Andric !EF->__sanitizer_acquire_crash_state()) 2940b57cec5SDimitry Andric return; 2950b57cec5SDimitry Andric Printf("ALARM: working on the last Unit for %zd seconds\n", Seconds); 2960b57cec5SDimitry Andric Printf(" and the timeout value is %d (use -timeout=N to change)\n", 2970b57cec5SDimitry Andric Options.UnitTimeoutSec); 2980b57cec5SDimitry Andric DumpCurrentUnit("timeout-"); 2990b57cec5SDimitry Andric Printf("==%lu== ERROR: libFuzzer: timeout after %d seconds\n", GetPid(), 3000b57cec5SDimitry Andric Seconds); 3010b57cec5SDimitry Andric PrintStackTrace(); 3020b57cec5SDimitry Andric Printf("SUMMARY: libFuzzer: timeout\n"); 3030b57cec5SDimitry Andric PrintFinalStats(); 3040b57cec5SDimitry Andric _Exit(Options.TimeoutExitCode); // Stop right now. 3050b57cec5SDimitry Andric } 3060b57cec5SDimitry Andric } 3070b57cec5SDimitry Andric 3080b57cec5SDimitry Andric void Fuzzer::RssLimitCallback() { 3090b57cec5SDimitry Andric if (EF->__sanitizer_acquire_crash_state && 3100b57cec5SDimitry Andric !EF->__sanitizer_acquire_crash_state()) 3110b57cec5SDimitry Andric return; 3120b57cec5SDimitry Andric Printf( 3130b57cec5SDimitry Andric "==%lu== ERROR: libFuzzer: out-of-memory (used: %zdMb; limit: %zdMb)\n", 3140b57cec5SDimitry Andric GetPid(), GetPeakRSSMb(), Options.RssLimitMb); 3150b57cec5SDimitry Andric Printf(" To change the out-of-memory limit use -rss_limit_mb=<N>\n\n"); 3160b57cec5SDimitry Andric PrintMemoryProfile(); 3170b57cec5SDimitry Andric DumpCurrentUnit("oom-"); 3180b57cec5SDimitry Andric Printf("SUMMARY: libFuzzer: out-of-memory\n"); 3190b57cec5SDimitry Andric PrintFinalStats(); 3200b57cec5SDimitry Andric _Exit(Options.OOMExitCode); // Stop right now. 3210b57cec5SDimitry Andric } 3220b57cec5SDimitry Andric 32368d75effSDimitry Andric void Fuzzer::PrintStats(const char *Where, const char *End, size_t Units, 32468d75effSDimitry Andric size_t Features) { 3250b57cec5SDimitry Andric size_t ExecPerSec = execPerSec(); 3260b57cec5SDimitry Andric if (!Options.Verbosity) 3270b57cec5SDimitry Andric return; 3280b57cec5SDimitry Andric Printf("#%zd\t%s", TotalNumberOfRuns, Where); 3290b57cec5SDimitry Andric if (size_t N = TPC.GetTotalPCCoverage()) 3300b57cec5SDimitry Andric Printf(" cov: %zd", N); 33168d75effSDimitry Andric if (size_t N = Features ? Features : Corpus.NumFeatures()) 3320b57cec5SDimitry Andric Printf(" ft: %zd", N); 3330b57cec5SDimitry Andric if (!Corpus.empty()) { 3340b57cec5SDimitry Andric Printf(" corp: %zd", Corpus.NumActiveUnits()); 3350b57cec5SDimitry Andric if (size_t N = Corpus.SizeInBytes()) { 3360b57cec5SDimitry Andric if (N < (1 << 14)) 3370b57cec5SDimitry Andric Printf("/%zdb", N); 3380b57cec5SDimitry Andric else if (N < (1 << 24)) 3390b57cec5SDimitry Andric Printf("/%zdKb", N >> 10); 3400b57cec5SDimitry Andric else 3410b57cec5SDimitry Andric Printf("/%zdMb", N >> 20); 3420b57cec5SDimitry Andric } 3430b57cec5SDimitry Andric if (size_t FF = Corpus.NumInputsThatTouchFocusFunction()) 3440b57cec5SDimitry Andric Printf(" focus: %zd", FF); 3450b57cec5SDimitry Andric } 3460b57cec5SDimitry Andric if (TmpMaxMutationLen) 3470b57cec5SDimitry Andric Printf(" lim: %zd", TmpMaxMutationLen); 3480b57cec5SDimitry Andric if (Units) 3490b57cec5SDimitry Andric Printf(" units: %zd", Units); 3500b57cec5SDimitry Andric 3510b57cec5SDimitry Andric Printf(" exec/s: %zd", ExecPerSec); 3520b57cec5SDimitry Andric Printf(" rss: %zdMb", GetPeakRSSMb()); 3530b57cec5SDimitry Andric Printf("%s", End); 3540b57cec5SDimitry Andric } 3550b57cec5SDimitry Andric 3560b57cec5SDimitry Andric void Fuzzer::PrintFinalStats() { 3570b57cec5SDimitry Andric if (Options.PrintCoverage) 3580b57cec5SDimitry Andric TPC.PrintCoverage(); 3590b57cec5SDimitry Andric if (Options.PrintCorpusStats) 3600b57cec5SDimitry Andric Corpus.PrintStats(); 3610b57cec5SDimitry Andric if (!Options.PrintFinalStats) 3620b57cec5SDimitry Andric return; 3630b57cec5SDimitry Andric size_t ExecPerSec = execPerSec(); 3640b57cec5SDimitry Andric Printf("stat::number_of_executed_units: %zd\n", TotalNumberOfRuns); 3650b57cec5SDimitry Andric Printf("stat::average_exec_per_sec: %zd\n", ExecPerSec); 3660b57cec5SDimitry Andric Printf("stat::new_units_added: %zd\n", NumberOfNewUnitsAdded); 3670b57cec5SDimitry Andric Printf("stat::slowest_unit_time_sec: %zd\n", TimeOfLongestUnitInSeconds); 3680b57cec5SDimitry Andric Printf("stat::peak_rss_mb: %zd\n", GetPeakRSSMb()); 3690b57cec5SDimitry Andric } 3700b57cec5SDimitry Andric 3710b57cec5SDimitry Andric void Fuzzer::SetMaxInputLen(size_t MaxInputLen) { 3720b57cec5SDimitry Andric assert(this->MaxInputLen == 0); // Can only reset MaxInputLen from 0 to non-0. 3730b57cec5SDimitry Andric assert(MaxInputLen); 3740b57cec5SDimitry Andric this->MaxInputLen = MaxInputLen; 3750b57cec5SDimitry Andric this->MaxMutationLen = MaxInputLen; 3760b57cec5SDimitry Andric AllocateCurrentUnitData(); 3770b57cec5SDimitry Andric Printf("INFO: -max_len is not provided; " 3780b57cec5SDimitry Andric "libFuzzer will not generate inputs larger than %zd bytes\n", 3790b57cec5SDimitry Andric MaxInputLen); 3800b57cec5SDimitry Andric } 3810b57cec5SDimitry Andric 3820b57cec5SDimitry Andric void Fuzzer::SetMaxMutationLen(size_t MaxMutationLen) { 3830b57cec5SDimitry Andric assert(MaxMutationLen && MaxMutationLen <= MaxInputLen); 3840b57cec5SDimitry Andric this->MaxMutationLen = MaxMutationLen; 3850b57cec5SDimitry Andric } 3860b57cec5SDimitry Andric 3870b57cec5SDimitry Andric void Fuzzer::CheckExitOnSrcPosOrItem() { 3880b57cec5SDimitry Andric if (!Options.ExitOnSrcPos.empty()) { 3890b57cec5SDimitry Andric static auto *PCsSet = new Set<uintptr_t>; 3900b57cec5SDimitry Andric auto HandlePC = [&](const TracePC::PCTableEntry *TE) { 3910b57cec5SDimitry Andric if (!PCsSet->insert(TE->PC).second) 3920b57cec5SDimitry Andric return; 3930b57cec5SDimitry Andric std::string Descr = DescribePC("%F %L", TE->PC + 1); 3940b57cec5SDimitry Andric if (Descr.find(Options.ExitOnSrcPos) != std::string::npos) { 3950b57cec5SDimitry Andric Printf("INFO: found line matching '%s', exiting.\n", 3960b57cec5SDimitry Andric Options.ExitOnSrcPos.c_str()); 3970b57cec5SDimitry Andric _Exit(0); 3980b57cec5SDimitry Andric } 3990b57cec5SDimitry Andric }; 4000b57cec5SDimitry Andric TPC.ForEachObservedPC(HandlePC); 4010b57cec5SDimitry Andric } 4020b57cec5SDimitry Andric if (!Options.ExitOnItem.empty()) { 4030b57cec5SDimitry Andric if (Corpus.HasUnit(Options.ExitOnItem)) { 4040b57cec5SDimitry Andric Printf("INFO: found item with checksum '%s', exiting.\n", 4050b57cec5SDimitry Andric Options.ExitOnItem.c_str()); 4060b57cec5SDimitry Andric _Exit(0); 4070b57cec5SDimitry Andric } 4080b57cec5SDimitry Andric } 4090b57cec5SDimitry Andric } 4100b57cec5SDimitry Andric 4110b57cec5SDimitry Andric void Fuzzer::RereadOutputCorpus(size_t MaxSize) { 4120b57cec5SDimitry Andric if (Options.OutputCorpus.empty() || !Options.ReloadIntervalSec) 4130b57cec5SDimitry Andric return; 4140b57cec5SDimitry Andric Vector<Unit> AdditionalCorpus; 4150b57cec5SDimitry Andric ReadDirToVectorOfUnits(Options.OutputCorpus.c_str(), &AdditionalCorpus, 4160b57cec5SDimitry Andric &EpochOfLastReadOfOutputCorpus, MaxSize, 4170b57cec5SDimitry Andric /*ExitOnError*/ false); 4180b57cec5SDimitry Andric if (Options.Verbosity >= 2) 4190b57cec5SDimitry Andric Printf("Reload: read %zd new units.\n", AdditionalCorpus.size()); 4200b57cec5SDimitry Andric bool Reloaded = false; 4210b57cec5SDimitry Andric for (auto &U : AdditionalCorpus) { 4220b57cec5SDimitry Andric if (U.size() > MaxSize) 4230b57cec5SDimitry Andric U.resize(MaxSize); 4240b57cec5SDimitry Andric if (!Corpus.HasUnit(U)) { 4250b57cec5SDimitry Andric if (RunOne(U.data(), U.size())) { 4260b57cec5SDimitry Andric CheckExitOnSrcPosOrItem(); 4270b57cec5SDimitry Andric Reloaded = true; 4280b57cec5SDimitry Andric } 4290b57cec5SDimitry Andric } 4300b57cec5SDimitry Andric } 4310b57cec5SDimitry Andric if (Reloaded) 4320b57cec5SDimitry Andric PrintStats("RELOAD"); 4330b57cec5SDimitry Andric } 4340b57cec5SDimitry Andric 4350b57cec5SDimitry Andric void Fuzzer::PrintPulseAndReportSlowInput(const uint8_t *Data, size_t Size) { 4360b57cec5SDimitry Andric auto TimeOfUnit = 4370b57cec5SDimitry Andric duration_cast<seconds>(UnitStopTime - UnitStartTime).count(); 4380b57cec5SDimitry Andric if (!(TotalNumberOfRuns & (TotalNumberOfRuns - 1)) && 4390b57cec5SDimitry Andric secondsSinceProcessStartUp() >= 2) 4400b57cec5SDimitry Andric PrintStats("pulse "); 4410b57cec5SDimitry Andric if (TimeOfUnit > TimeOfLongestUnitInSeconds * 1.1 && 4420b57cec5SDimitry Andric TimeOfUnit >= Options.ReportSlowUnits) { 4430b57cec5SDimitry Andric TimeOfLongestUnitInSeconds = TimeOfUnit; 4440b57cec5SDimitry Andric Printf("Slowest unit: %zd s:\n", TimeOfLongestUnitInSeconds); 4450b57cec5SDimitry Andric WriteUnitToFileWithPrefix({Data, Data + Size}, "slow-unit-"); 4460b57cec5SDimitry Andric } 4470b57cec5SDimitry Andric } 4480b57cec5SDimitry Andric 4490b57cec5SDimitry Andric static void WriteFeatureSetToFile(const std::string &FeaturesDir, 4500b57cec5SDimitry Andric const std::string &FileName, 4510b57cec5SDimitry Andric const Vector<uint32_t> &FeatureSet) { 4520b57cec5SDimitry Andric if (FeaturesDir.empty() || FeatureSet.empty()) return; 4530b57cec5SDimitry Andric WriteToFile(reinterpret_cast<const uint8_t *>(FeatureSet.data()), 4540b57cec5SDimitry Andric FeatureSet.size() * sizeof(FeatureSet[0]), 4550b57cec5SDimitry Andric DirPlusFile(FeaturesDir, FileName)); 4560b57cec5SDimitry Andric } 4570b57cec5SDimitry Andric 4580b57cec5SDimitry Andric static void RenameFeatureSetFile(const std::string &FeaturesDir, 4590b57cec5SDimitry Andric const std::string &OldFile, 4600b57cec5SDimitry Andric const std::string &NewFile) { 4610b57cec5SDimitry Andric if (FeaturesDir.empty()) return; 4620b57cec5SDimitry Andric RenameFile(DirPlusFile(FeaturesDir, OldFile), 4630b57cec5SDimitry Andric DirPlusFile(FeaturesDir, NewFile)); 4640b57cec5SDimitry Andric } 4650b57cec5SDimitry Andric 4660b57cec5SDimitry Andric bool Fuzzer::RunOne(const uint8_t *Data, size_t Size, bool MayDeleteFile, 4670b57cec5SDimitry Andric InputInfo *II, bool *FoundUniqFeatures) { 4680b57cec5SDimitry Andric if (!Size) 4690b57cec5SDimitry Andric return false; 4700b57cec5SDimitry Andric 4710b57cec5SDimitry Andric ExecuteCallback(Data, Size); 4720b57cec5SDimitry Andric 4730b57cec5SDimitry Andric UniqFeatureSetTmp.clear(); 4740b57cec5SDimitry Andric size_t FoundUniqFeaturesOfII = 0; 4750b57cec5SDimitry Andric size_t NumUpdatesBefore = Corpus.NumFeatureUpdates(); 4760b57cec5SDimitry Andric TPC.CollectFeatures([&](size_t Feature) { 4770b57cec5SDimitry Andric if (Corpus.AddFeature(Feature, Size, Options.Shrink)) 4780b57cec5SDimitry Andric UniqFeatureSetTmp.push_back(Feature); 479*5ffd83dbSDimitry Andric if (Options.Entropic) 480*5ffd83dbSDimitry Andric Corpus.UpdateFeatureFrequency(II, Feature); 4810b57cec5SDimitry Andric if (Options.ReduceInputs && II) 4820b57cec5SDimitry Andric if (std::binary_search(II->UniqFeatureSet.begin(), 4830b57cec5SDimitry Andric II->UniqFeatureSet.end(), Feature)) 4840b57cec5SDimitry Andric FoundUniqFeaturesOfII++; 4850b57cec5SDimitry Andric }); 4860b57cec5SDimitry Andric if (FoundUniqFeatures) 4870b57cec5SDimitry Andric *FoundUniqFeatures = FoundUniqFeaturesOfII; 4880b57cec5SDimitry Andric PrintPulseAndReportSlowInput(Data, Size); 4890b57cec5SDimitry Andric size_t NumNewFeatures = Corpus.NumFeatureUpdates() - NumUpdatesBefore; 4900b57cec5SDimitry Andric if (NumNewFeatures) { 4910b57cec5SDimitry Andric TPC.UpdateObservedPCs(); 4920b57cec5SDimitry Andric auto NewII = Corpus.AddToCorpus({Data, Data + Size}, NumNewFeatures, 4930b57cec5SDimitry Andric MayDeleteFile, TPC.ObservedFocusFunction(), 4940b57cec5SDimitry Andric UniqFeatureSetTmp, DFT, II); 4950b57cec5SDimitry Andric WriteFeatureSetToFile(Options.FeaturesDir, Sha1ToString(NewII->Sha1), 4960b57cec5SDimitry Andric NewII->UniqFeatureSet); 4970b57cec5SDimitry Andric return true; 4980b57cec5SDimitry Andric } 4990b57cec5SDimitry Andric if (II && FoundUniqFeaturesOfII && 5000b57cec5SDimitry Andric II->DataFlowTraceForFocusFunction.empty() && 5010b57cec5SDimitry Andric FoundUniqFeaturesOfII == II->UniqFeatureSet.size() && 5020b57cec5SDimitry Andric II->U.size() > Size) { 5030b57cec5SDimitry Andric auto OldFeaturesFile = Sha1ToString(II->Sha1); 5040b57cec5SDimitry Andric Corpus.Replace(II, {Data, Data + Size}); 5050b57cec5SDimitry Andric RenameFeatureSetFile(Options.FeaturesDir, OldFeaturesFile, 5060b57cec5SDimitry Andric Sha1ToString(II->Sha1)); 5070b57cec5SDimitry Andric return true; 5080b57cec5SDimitry Andric } 5090b57cec5SDimitry Andric return false; 5100b57cec5SDimitry Andric } 5110b57cec5SDimitry Andric 5120b57cec5SDimitry Andric size_t Fuzzer::GetCurrentUnitInFuzzingThead(const uint8_t **Data) const { 5130b57cec5SDimitry Andric assert(InFuzzingThread()); 5140b57cec5SDimitry Andric *Data = CurrentUnitData; 5150b57cec5SDimitry Andric return CurrentUnitSize; 5160b57cec5SDimitry Andric } 5170b57cec5SDimitry Andric 5180b57cec5SDimitry Andric void Fuzzer::CrashOnOverwrittenData() { 51968d75effSDimitry Andric Printf("==%d== ERROR: libFuzzer: fuzz target overwrites its const input\n", 5200b57cec5SDimitry Andric GetPid()); 52168d75effSDimitry Andric PrintStackTrace(); 52268d75effSDimitry Andric Printf("SUMMARY: libFuzzer: overwrites-const-input\n"); 5230b57cec5SDimitry Andric DumpCurrentUnit("crash-"); 52468d75effSDimitry Andric PrintFinalStats(); 5250b57cec5SDimitry Andric _Exit(Options.ErrorExitCode); // Stop right now. 5260b57cec5SDimitry Andric } 5270b57cec5SDimitry Andric 5280b57cec5SDimitry Andric // Compare two arrays, but not all bytes if the arrays are large. 5290b57cec5SDimitry Andric static bool LooseMemeq(const uint8_t *A, const uint8_t *B, size_t Size) { 5300b57cec5SDimitry Andric const size_t Limit = 64; 5310b57cec5SDimitry Andric if (Size <= 64) 5320b57cec5SDimitry Andric return !memcmp(A, B, Size); 5330b57cec5SDimitry Andric // Compare first and last Limit/2 bytes. 5340b57cec5SDimitry Andric return !memcmp(A, B, Limit / 2) && 5350b57cec5SDimitry Andric !memcmp(A + Size - Limit / 2, B + Size - Limit / 2, Limit / 2); 5360b57cec5SDimitry Andric } 5370b57cec5SDimitry Andric 5380b57cec5SDimitry Andric void Fuzzer::ExecuteCallback(const uint8_t *Data, size_t Size) { 5390b57cec5SDimitry Andric TPC.RecordInitialStack(); 5400b57cec5SDimitry Andric TotalNumberOfRuns++; 5410b57cec5SDimitry Andric assert(InFuzzingThread()); 5420b57cec5SDimitry Andric // We copy the contents of Unit into a separate heap buffer 5430b57cec5SDimitry Andric // so that we reliably find buffer overflows in it. 5440b57cec5SDimitry Andric uint8_t *DataCopy = new uint8_t[Size]; 5450b57cec5SDimitry Andric memcpy(DataCopy, Data, Size); 5460b57cec5SDimitry Andric if (EF->__msan_unpoison) 5470b57cec5SDimitry Andric EF->__msan_unpoison(DataCopy, Size); 5480b57cec5SDimitry Andric if (EF->__msan_unpoison_param) 5490b57cec5SDimitry Andric EF->__msan_unpoison_param(2); 5500b57cec5SDimitry Andric if (CurrentUnitData && CurrentUnitData != Data) 5510b57cec5SDimitry Andric memcpy(CurrentUnitData, Data, Size); 5520b57cec5SDimitry Andric CurrentUnitSize = Size; 5530b57cec5SDimitry Andric { 5540b57cec5SDimitry Andric ScopedEnableMsanInterceptorChecks S; 5550b57cec5SDimitry Andric AllocTracer.Start(Options.TraceMalloc); 5560b57cec5SDimitry Andric UnitStartTime = system_clock::now(); 5570b57cec5SDimitry Andric TPC.ResetMaps(); 5580b57cec5SDimitry Andric RunningUserCallback = true; 5590b57cec5SDimitry Andric int Res = CB(DataCopy, Size); 5600b57cec5SDimitry Andric RunningUserCallback = false; 5610b57cec5SDimitry Andric UnitStopTime = system_clock::now(); 5620b57cec5SDimitry Andric (void)Res; 5630b57cec5SDimitry Andric assert(Res == 0); 5640b57cec5SDimitry Andric HasMoreMallocsThanFrees = AllocTracer.Stop(); 5650b57cec5SDimitry Andric } 5660b57cec5SDimitry Andric if (!LooseMemeq(DataCopy, Data, Size)) 5670b57cec5SDimitry Andric CrashOnOverwrittenData(); 5680b57cec5SDimitry Andric CurrentUnitSize = 0; 5690b57cec5SDimitry Andric delete[] DataCopy; 5700b57cec5SDimitry Andric } 5710b57cec5SDimitry Andric 5720b57cec5SDimitry Andric std::string Fuzzer::WriteToOutputCorpus(const Unit &U) { 5730b57cec5SDimitry Andric if (Options.OnlyASCII) 5740b57cec5SDimitry Andric assert(IsASCII(U)); 5750b57cec5SDimitry Andric if (Options.OutputCorpus.empty()) 5760b57cec5SDimitry Andric return ""; 5770b57cec5SDimitry Andric std::string Path = DirPlusFile(Options.OutputCorpus, Hash(U)); 5780b57cec5SDimitry Andric WriteToFile(U, Path); 5790b57cec5SDimitry Andric if (Options.Verbosity >= 2) 5800b57cec5SDimitry Andric Printf("Written %zd bytes to %s\n", U.size(), Path.c_str()); 5810b57cec5SDimitry Andric return Path; 5820b57cec5SDimitry Andric } 5830b57cec5SDimitry Andric 5840b57cec5SDimitry Andric void Fuzzer::WriteUnitToFileWithPrefix(const Unit &U, const char *Prefix) { 5850b57cec5SDimitry Andric if (!Options.SaveArtifacts) 5860b57cec5SDimitry Andric return; 5870b57cec5SDimitry Andric std::string Path = Options.ArtifactPrefix + Prefix + Hash(U); 5880b57cec5SDimitry Andric if (!Options.ExactArtifactPath.empty()) 5890b57cec5SDimitry Andric Path = Options.ExactArtifactPath; // Overrides ArtifactPrefix. 5900b57cec5SDimitry Andric WriteToFile(U, Path); 5910b57cec5SDimitry Andric Printf("artifact_prefix='%s'; Test unit written to %s\n", 5920b57cec5SDimitry Andric Options.ArtifactPrefix.c_str(), Path.c_str()); 5930b57cec5SDimitry Andric if (U.size() <= kMaxUnitSizeToPrint) 5940b57cec5SDimitry Andric Printf("Base64: %s\n", Base64(U).c_str()); 5950b57cec5SDimitry Andric } 5960b57cec5SDimitry Andric 5970b57cec5SDimitry Andric void Fuzzer::PrintStatusForNewUnit(const Unit &U, const char *Text) { 5980b57cec5SDimitry Andric if (!Options.PrintNEW) 5990b57cec5SDimitry Andric return; 6000b57cec5SDimitry Andric PrintStats(Text, ""); 6010b57cec5SDimitry Andric if (Options.Verbosity) { 6020b57cec5SDimitry Andric Printf(" L: %zd/%zd ", U.size(), Corpus.MaxInputSize()); 6030b57cec5SDimitry Andric MD.PrintMutationSequence(); 6040b57cec5SDimitry Andric Printf("\n"); 6050b57cec5SDimitry Andric } 6060b57cec5SDimitry Andric } 6070b57cec5SDimitry Andric 6080b57cec5SDimitry Andric void Fuzzer::ReportNewCoverage(InputInfo *II, const Unit &U) { 6090b57cec5SDimitry Andric II->NumSuccessfullMutations++; 6100b57cec5SDimitry Andric MD.RecordSuccessfulMutationSequence(); 6110b57cec5SDimitry Andric PrintStatusForNewUnit(U, II->Reduced ? "REDUCE" : "NEW "); 6120b57cec5SDimitry Andric WriteToOutputCorpus(U); 6130b57cec5SDimitry Andric NumberOfNewUnitsAdded++; 6140b57cec5SDimitry Andric CheckExitOnSrcPosOrItem(); // Check only after the unit is saved to corpus. 6150b57cec5SDimitry Andric LastCorpusUpdateRun = TotalNumberOfRuns; 6160b57cec5SDimitry Andric } 6170b57cec5SDimitry Andric 6180b57cec5SDimitry Andric // Tries detecting a memory leak on the particular input that we have just 6190b57cec5SDimitry Andric // executed before calling this function. 6200b57cec5SDimitry Andric void Fuzzer::TryDetectingAMemoryLeak(const uint8_t *Data, size_t Size, 6210b57cec5SDimitry Andric bool DuringInitialCorpusExecution) { 6220b57cec5SDimitry Andric if (!HasMoreMallocsThanFrees) 6230b57cec5SDimitry Andric return; // mallocs==frees, a leak is unlikely. 6240b57cec5SDimitry Andric if (!Options.DetectLeaks) 6250b57cec5SDimitry Andric return; 6260b57cec5SDimitry Andric if (!DuringInitialCorpusExecution && 6270b57cec5SDimitry Andric TotalNumberOfRuns >= Options.MaxNumberOfRuns) 6280b57cec5SDimitry Andric return; 6290b57cec5SDimitry Andric if (!&(EF->__lsan_enable) || !&(EF->__lsan_disable) || 6300b57cec5SDimitry Andric !(EF->__lsan_do_recoverable_leak_check)) 6310b57cec5SDimitry Andric return; // No lsan. 6320b57cec5SDimitry Andric // Run the target once again, but with lsan disabled so that if there is 6330b57cec5SDimitry Andric // a real leak we do not report it twice. 6340b57cec5SDimitry Andric EF->__lsan_disable(); 6350b57cec5SDimitry Andric ExecuteCallback(Data, Size); 6360b57cec5SDimitry Andric EF->__lsan_enable(); 6370b57cec5SDimitry Andric if (!HasMoreMallocsThanFrees) 6380b57cec5SDimitry Andric return; // a leak is unlikely. 6390b57cec5SDimitry Andric if (NumberOfLeakDetectionAttempts++ > 1000) { 6400b57cec5SDimitry Andric Options.DetectLeaks = false; 6410b57cec5SDimitry Andric Printf("INFO: libFuzzer disabled leak detection after every mutation.\n" 6420b57cec5SDimitry Andric " Most likely the target function accumulates allocated\n" 6430b57cec5SDimitry Andric " memory in a global state w/o actually leaking it.\n" 6440b57cec5SDimitry Andric " You may try running this binary with -trace_malloc=[12]" 6450b57cec5SDimitry Andric " to get a trace of mallocs and frees.\n" 6460b57cec5SDimitry Andric " If LeakSanitizer is enabled in this process it will still\n" 6470b57cec5SDimitry Andric " run on the process shutdown.\n"); 6480b57cec5SDimitry Andric return; 6490b57cec5SDimitry Andric } 6500b57cec5SDimitry Andric // Now perform the actual lsan pass. This is expensive and we must ensure 6510b57cec5SDimitry Andric // we don't call it too often. 6520b57cec5SDimitry Andric if (EF->__lsan_do_recoverable_leak_check()) { // Leak is found, report it. 6530b57cec5SDimitry Andric if (DuringInitialCorpusExecution) 6540b57cec5SDimitry Andric Printf("\nINFO: a leak has been found in the initial corpus.\n\n"); 6550b57cec5SDimitry Andric Printf("INFO: to ignore leaks on libFuzzer side use -detect_leaks=0.\n\n"); 6560b57cec5SDimitry Andric CurrentUnitSize = Size; 6570b57cec5SDimitry Andric DumpCurrentUnit("leak-"); 6580b57cec5SDimitry Andric PrintFinalStats(); 6590b57cec5SDimitry Andric _Exit(Options.ErrorExitCode); // not exit() to disable lsan further on. 6600b57cec5SDimitry Andric } 6610b57cec5SDimitry Andric } 6620b57cec5SDimitry Andric 6630b57cec5SDimitry Andric void Fuzzer::MutateAndTestOne() { 6640b57cec5SDimitry Andric MD.StartMutationSequence(); 6650b57cec5SDimitry Andric 6660b57cec5SDimitry Andric auto &II = Corpus.ChooseUnitToMutate(MD.GetRand()); 6670b57cec5SDimitry Andric if (Options.DoCrossOver) 6680b57cec5SDimitry Andric MD.SetCrossOverWith(&Corpus.ChooseUnitToMutate(MD.GetRand()).U); 6690b57cec5SDimitry Andric const auto &U = II.U; 6700b57cec5SDimitry Andric memcpy(BaseSha1, II.Sha1, sizeof(BaseSha1)); 6710b57cec5SDimitry Andric assert(CurrentUnitData); 6720b57cec5SDimitry Andric size_t Size = U.size(); 6730b57cec5SDimitry Andric assert(Size <= MaxInputLen && "Oversized Unit"); 6740b57cec5SDimitry Andric memcpy(CurrentUnitData, U.data(), Size); 6750b57cec5SDimitry Andric 6760b57cec5SDimitry Andric assert(MaxMutationLen > 0); 6770b57cec5SDimitry Andric 6780b57cec5SDimitry Andric size_t CurrentMaxMutationLen = 6790b57cec5SDimitry Andric Min(MaxMutationLen, Max(U.size(), TmpMaxMutationLen)); 6800b57cec5SDimitry Andric assert(CurrentMaxMutationLen > 0); 6810b57cec5SDimitry Andric 6820b57cec5SDimitry Andric for (int i = 0; i < Options.MutateDepth; i++) { 6830b57cec5SDimitry Andric if (TotalNumberOfRuns >= Options.MaxNumberOfRuns) 6840b57cec5SDimitry Andric break; 6850b57cec5SDimitry Andric MaybeExitGracefully(); 6860b57cec5SDimitry Andric size_t NewSize = 0; 6870b57cec5SDimitry Andric if (II.HasFocusFunction && !II.DataFlowTraceForFocusFunction.empty() && 6880b57cec5SDimitry Andric Size <= CurrentMaxMutationLen) 6890b57cec5SDimitry Andric NewSize = MD.MutateWithMask(CurrentUnitData, Size, Size, 6900b57cec5SDimitry Andric II.DataFlowTraceForFocusFunction); 6910b57cec5SDimitry Andric 6920b57cec5SDimitry Andric // If MutateWithMask either failed or wasn't called, call default Mutate. 6930b57cec5SDimitry Andric if (!NewSize) 6940b57cec5SDimitry Andric NewSize = MD.Mutate(CurrentUnitData, Size, CurrentMaxMutationLen); 6950b57cec5SDimitry Andric assert(NewSize > 0 && "Mutator returned empty unit"); 6960b57cec5SDimitry Andric assert(NewSize <= CurrentMaxMutationLen && "Mutator return oversized unit"); 6970b57cec5SDimitry Andric Size = NewSize; 6980b57cec5SDimitry Andric II.NumExecutedMutations++; 699*5ffd83dbSDimitry Andric Corpus.IncrementNumExecutedMutations(); 7000b57cec5SDimitry Andric 7010b57cec5SDimitry Andric bool FoundUniqFeatures = false; 7020b57cec5SDimitry Andric bool NewCov = RunOne(CurrentUnitData, Size, /*MayDeleteFile=*/true, &II, 7030b57cec5SDimitry Andric &FoundUniqFeatures); 7040b57cec5SDimitry Andric TryDetectingAMemoryLeak(CurrentUnitData, Size, 7050b57cec5SDimitry Andric /*DuringInitialCorpusExecution*/ false); 7060b57cec5SDimitry Andric if (NewCov) { 7070b57cec5SDimitry Andric ReportNewCoverage(&II, {CurrentUnitData, CurrentUnitData + Size}); 7080b57cec5SDimitry Andric break; // We will mutate this input more in the next rounds. 7090b57cec5SDimitry Andric } 7100b57cec5SDimitry Andric if (Options.ReduceDepth && !FoundUniqFeatures) 7110b57cec5SDimitry Andric break; 7120b57cec5SDimitry Andric } 713*5ffd83dbSDimitry Andric 714*5ffd83dbSDimitry Andric II.NeedsEnergyUpdate = true; 7150b57cec5SDimitry Andric } 7160b57cec5SDimitry Andric 7170b57cec5SDimitry Andric void Fuzzer::PurgeAllocator() { 7180b57cec5SDimitry Andric if (Options.PurgeAllocatorIntervalSec < 0 || !EF->__sanitizer_purge_allocator) 7190b57cec5SDimitry Andric return; 7200b57cec5SDimitry Andric if (duration_cast<seconds>(system_clock::now() - 7210b57cec5SDimitry Andric LastAllocatorPurgeAttemptTime) 7220b57cec5SDimitry Andric .count() < Options.PurgeAllocatorIntervalSec) 7230b57cec5SDimitry Andric return; 7240b57cec5SDimitry Andric 7250b57cec5SDimitry Andric if (Options.RssLimitMb <= 0 || 7260b57cec5SDimitry Andric GetPeakRSSMb() > static_cast<size_t>(Options.RssLimitMb) / 2) 7270b57cec5SDimitry Andric EF->__sanitizer_purge_allocator(); 7280b57cec5SDimitry Andric 7290b57cec5SDimitry Andric LastAllocatorPurgeAttemptTime = system_clock::now(); 7300b57cec5SDimitry Andric } 7310b57cec5SDimitry Andric 7320b57cec5SDimitry Andric void Fuzzer::ReadAndExecuteSeedCorpora(Vector<SizedFile> &CorporaFiles) { 7330b57cec5SDimitry Andric const size_t kMaxSaneLen = 1 << 20; 7340b57cec5SDimitry Andric const size_t kMinDefaultLen = 4096; 7350b57cec5SDimitry Andric size_t MaxSize = 0; 7360b57cec5SDimitry Andric size_t MinSize = -1; 7370b57cec5SDimitry Andric size_t TotalSize = 0; 7380b57cec5SDimitry Andric for (auto &File : CorporaFiles) { 7390b57cec5SDimitry Andric MaxSize = Max(File.Size, MaxSize); 7400b57cec5SDimitry Andric MinSize = Min(File.Size, MinSize); 7410b57cec5SDimitry Andric TotalSize += File.Size; 7420b57cec5SDimitry Andric } 7430b57cec5SDimitry Andric if (Options.MaxLen == 0) 7440b57cec5SDimitry Andric SetMaxInputLen(std::min(std::max(kMinDefaultLen, MaxSize), kMaxSaneLen)); 7450b57cec5SDimitry Andric assert(MaxInputLen > 0); 7460b57cec5SDimitry Andric 7470b57cec5SDimitry Andric // Test the callback with empty input and never try it again. 7480b57cec5SDimitry Andric uint8_t dummy = 0; 7490b57cec5SDimitry Andric ExecuteCallback(&dummy, 0); 7500b57cec5SDimitry Andric 7510b57cec5SDimitry Andric if (CorporaFiles.empty()) { 7520b57cec5SDimitry Andric Printf("INFO: A corpus is not provided, starting from an empty corpus\n"); 7530b57cec5SDimitry Andric Unit U({'\n'}); // Valid ASCII input. 7540b57cec5SDimitry Andric RunOne(U.data(), U.size()); 7550b57cec5SDimitry Andric } else { 7560b57cec5SDimitry Andric Printf("INFO: seed corpus: files: %zd min: %zdb max: %zdb total: %zdb" 7570b57cec5SDimitry Andric " rss: %zdMb\n", 7580b57cec5SDimitry Andric CorporaFiles.size(), MinSize, MaxSize, TotalSize, GetPeakRSSMb()); 7590b57cec5SDimitry Andric if (Options.ShuffleAtStartUp) 7600b57cec5SDimitry Andric std::shuffle(CorporaFiles.begin(), CorporaFiles.end(), MD.GetRand()); 7610b57cec5SDimitry Andric 7620b57cec5SDimitry Andric if (Options.PreferSmall) { 7630b57cec5SDimitry Andric std::stable_sort(CorporaFiles.begin(), CorporaFiles.end()); 7640b57cec5SDimitry Andric assert(CorporaFiles.front().Size <= CorporaFiles.back().Size); 7650b57cec5SDimitry Andric } 7660b57cec5SDimitry Andric 7670b57cec5SDimitry Andric // Load and execute inputs one by one. 7680b57cec5SDimitry Andric for (auto &SF : CorporaFiles) { 7690b57cec5SDimitry Andric auto U = FileToVector(SF.File, MaxInputLen, /*ExitOnError=*/false); 7700b57cec5SDimitry Andric assert(U.size() <= MaxInputLen); 7710b57cec5SDimitry Andric RunOne(U.data(), U.size()); 7720b57cec5SDimitry Andric CheckExitOnSrcPosOrItem(); 7730b57cec5SDimitry Andric TryDetectingAMemoryLeak(U.data(), U.size(), 7740b57cec5SDimitry Andric /*DuringInitialCorpusExecution*/ true); 7750b57cec5SDimitry Andric } 7760b57cec5SDimitry Andric } 7770b57cec5SDimitry Andric 7780b57cec5SDimitry Andric PrintStats("INITED"); 779*5ffd83dbSDimitry Andric if (!Options.FocusFunction.empty()) { 7800b57cec5SDimitry Andric Printf("INFO: %zd/%zd inputs touch the focus function\n", 7810b57cec5SDimitry Andric Corpus.NumInputsThatTouchFocusFunction(), Corpus.size()); 7820b57cec5SDimitry Andric if (!Options.DataFlowTrace.empty()) 7830b57cec5SDimitry Andric Printf("INFO: %zd/%zd inputs have the Data Flow Trace\n", 784*5ffd83dbSDimitry Andric Corpus.NumInputsWithDataFlowTrace(), 785*5ffd83dbSDimitry Andric Corpus.NumInputsThatTouchFocusFunction()); 786*5ffd83dbSDimitry Andric } 7870b57cec5SDimitry Andric 7880b57cec5SDimitry Andric if (Corpus.empty() && Options.MaxNumberOfRuns) { 7890b57cec5SDimitry Andric Printf("ERROR: no interesting inputs were found. " 7900b57cec5SDimitry Andric "Is the code instrumented for coverage? Exiting.\n"); 7910b57cec5SDimitry Andric exit(1); 7920b57cec5SDimitry Andric } 7930b57cec5SDimitry Andric } 7940b57cec5SDimitry Andric 7950b57cec5SDimitry Andric void Fuzzer::Loop(Vector<SizedFile> &CorporaFiles) { 7960b57cec5SDimitry Andric auto FocusFunctionOrAuto = Options.FocusFunction; 7970b57cec5SDimitry Andric DFT.Init(Options.DataFlowTrace, &FocusFunctionOrAuto, CorporaFiles, 7980b57cec5SDimitry Andric MD.GetRand()); 7990b57cec5SDimitry Andric TPC.SetFocusFunction(FocusFunctionOrAuto); 8000b57cec5SDimitry Andric ReadAndExecuteSeedCorpora(CorporaFiles); 8010b57cec5SDimitry Andric DFT.Clear(); // No need for DFT any more. 8020b57cec5SDimitry Andric TPC.SetPrintNewPCs(Options.PrintNewCovPcs); 8030b57cec5SDimitry Andric TPC.SetPrintNewFuncs(Options.PrintNewCovFuncs); 8040b57cec5SDimitry Andric system_clock::time_point LastCorpusReload = system_clock::now(); 8050b57cec5SDimitry Andric 8060b57cec5SDimitry Andric TmpMaxMutationLen = 8070b57cec5SDimitry Andric Min(MaxMutationLen, Max(size_t(4), Corpus.MaxInputSize())); 8080b57cec5SDimitry Andric 8090b57cec5SDimitry Andric while (true) { 8100b57cec5SDimitry Andric auto Now = system_clock::now(); 8110b57cec5SDimitry Andric if (!Options.StopFile.empty() && 8120b57cec5SDimitry Andric !FileToVector(Options.StopFile, 1, false).empty()) 8130b57cec5SDimitry Andric break; 8140b57cec5SDimitry Andric if (duration_cast<seconds>(Now - LastCorpusReload).count() >= 8150b57cec5SDimitry Andric Options.ReloadIntervalSec) { 8160b57cec5SDimitry Andric RereadOutputCorpus(MaxInputLen); 8170b57cec5SDimitry Andric LastCorpusReload = system_clock::now(); 8180b57cec5SDimitry Andric } 8190b57cec5SDimitry Andric if (TotalNumberOfRuns >= Options.MaxNumberOfRuns) 8200b57cec5SDimitry Andric break; 8210b57cec5SDimitry Andric if (TimedOut()) 8220b57cec5SDimitry Andric break; 8230b57cec5SDimitry Andric 8240b57cec5SDimitry Andric // Update TmpMaxMutationLen 8250b57cec5SDimitry Andric if (Options.LenControl) { 8260b57cec5SDimitry Andric if (TmpMaxMutationLen < MaxMutationLen && 8270b57cec5SDimitry Andric TotalNumberOfRuns - LastCorpusUpdateRun > 8280b57cec5SDimitry Andric Options.LenControl * Log(TmpMaxMutationLen)) { 8290b57cec5SDimitry Andric TmpMaxMutationLen = 8300b57cec5SDimitry Andric Min(MaxMutationLen, TmpMaxMutationLen + Log(TmpMaxMutationLen)); 8310b57cec5SDimitry Andric LastCorpusUpdateRun = TotalNumberOfRuns; 8320b57cec5SDimitry Andric } 8330b57cec5SDimitry Andric } else { 8340b57cec5SDimitry Andric TmpMaxMutationLen = MaxMutationLen; 8350b57cec5SDimitry Andric } 8360b57cec5SDimitry Andric 8370b57cec5SDimitry Andric // Perform several mutations and runs. 8380b57cec5SDimitry Andric MutateAndTestOne(); 8390b57cec5SDimitry Andric 8400b57cec5SDimitry Andric PurgeAllocator(); 8410b57cec5SDimitry Andric } 8420b57cec5SDimitry Andric 8430b57cec5SDimitry Andric PrintStats("DONE ", "\n"); 8440b57cec5SDimitry Andric MD.PrintRecommendedDictionary(); 8450b57cec5SDimitry Andric } 8460b57cec5SDimitry Andric 8470b57cec5SDimitry Andric void Fuzzer::MinimizeCrashLoop(const Unit &U) { 8480b57cec5SDimitry Andric if (U.size() <= 1) 8490b57cec5SDimitry Andric return; 8500b57cec5SDimitry Andric while (!TimedOut() && TotalNumberOfRuns < Options.MaxNumberOfRuns) { 8510b57cec5SDimitry Andric MD.StartMutationSequence(); 8520b57cec5SDimitry Andric memcpy(CurrentUnitData, U.data(), U.size()); 8530b57cec5SDimitry Andric for (int i = 0; i < Options.MutateDepth; i++) { 8540b57cec5SDimitry Andric size_t NewSize = MD.Mutate(CurrentUnitData, U.size(), MaxMutationLen); 8550b57cec5SDimitry Andric assert(NewSize > 0 && NewSize <= MaxMutationLen); 8560b57cec5SDimitry Andric ExecuteCallback(CurrentUnitData, NewSize); 8570b57cec5SDimitry Andric PrintPulseAndReportSlowInput(CurrentUnitData, NewSize); 8580b57cec5SDimitry Andric TryDetectingAMemoryLeak(CurrentUnitData, NewSize, 8590b57cec5SDimitry Andric /*DuringInitialCorpusExecution*/ false); 8600b57cec5SDimitry Andric } 8610b57cec5SDimitry Andric } 8620b57cec5SDimitry Andric } 8630b57cec5SDimitry Andric 8640b57cec5SDimitry Andric } // namespace fuzzer 8650b57cec5SDimitry Andric 8660b57cec5SDimitry Andric extern "C" { 8670b57cec5SDimitry Andric 8680b57cec5SDimitry Andric ATTRIBUTE_INTERFACE size_t 8690b57cec5SDimitry Andric LLVMFuzzerMutate(uint8_t *Data, size_t Size, size_t MaxSize) { 8700b57cec5SDimitry Andric assert(fuzzer::F); 8710b57cec5SDimitry Andric return fuzzer::F->GetMD().DefaultMutate(Data, Size, MaxSize); 8720b57cec5SDimitry Andric } 8730b57cec5SDimitry Andric 8740b57cec5SDimitry Andric } // extern "C" 875