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" 155ffd83dbSDimitry 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()); 2605ffd83dbSDimitry Andric RmDirRecursive(TempPath("FuzzWithFork", ".dir")); 2610b57cec5SDimitry Andric F->PrintFinalStats(); 2620b57cec5SDimitry Andric _Exit(0); 2630b57cec5SDimitry Andric } 2640b57cec5SDimitry Andric 265*bdd1243dSDimitry Andric int Fuzzer::InterruptExitCode() { 266*bdd1243dSDimitry Andric assert(F); 267*bdd1243dSDimitry Andric return F->Options.InterruptExitCode; 268*bdd1243dSDimitry Andric } 269*bdd1243dSDimitry Andric 2700b57cec5SDimitry Andric void Fuzzer::InterruptCallback() { 2710b57cec5SDimitry Andric Printf("==%lu== libFuzzer: run interrupted; exiting\n", GetPid()); 2720b57cec5SDimitry Andric PrintFinalStats(); 2730b57cec5SDimitry Andric ScopedDisableMsanInterceptorChecks S; // RmDirRecursive may call opendir(). 2745ffd83dbSDimitry Andric RmDirRecursive(TempPath("FuzzWithFork", ".dir")); 2750b57cec5SDimitry Andric // Stop right now, don't perform any at-exit actions. 2760b57cec5SDimitry Andric _Exit(Options.InterruptExitCode); 2770b57cec5SDimitry Andric } 2780b57cec5SDimitry Andric 2790b57cec5SDimitry Andric NO_SANITIZE_MEMORY 2800b57cec5SDimitry Andric void Fuzzer::AlarmCallback() { 2810b57cec5SDimitry Andric assert(Options.UnitTimeoutSec > 0); 28268d75effSDimitry Andric // In Windows and Fuchsia, Alarm callback is executed by a different thread. 2830b57cec5SDimitry Andric // NetBSD's current behavior needs this change too. 28468d75effSDimitry Andric #if !LIBFUZZER_WINDOWS && !LIBFUZZER_NETBSD && !LIBFUZZER_FUCHSIA 2850b57cec5SDimitry Andric if (!InFuzzingThread()) 2860b57cec5SDimitry Andric return; 2870b57cec5SDimitry Andric #endif 2880b57cec5SDimitry Andric if (!RunningUserCallback) 2890b57cec5SDimitry Andric return; // We have not started running units yet. 2900b57cec5SDimitry Andric size_t Seconds = 2910b57cec5SDimitry Andric duration_cast<seconds>(system_clock::now() - UnitStartTime).count(); 2920b57cec5SDimitry Andric if (Seconds == 0) 2930b57cec5SDimitry Andric return; 2940b57cec5SDimitry Andric if (Options.Verbosity >= 2) 2950b57cec5SDimitry Andric Printf("AlarmCallback %zd\n", Seconds); 2960b57cec5SDimitry Andric if (Seconds >= (size_t)Options.UnitTimeoutSec) { 2970b57cec5SDimitry Andric if (EF->__sanitizer_acquire_crash_state && 2980b57cec5SDimitry Andric !EF->__sanitizer_acquire_crash_state()) 2990b57cec5SDimitry Andric return; 3000b57cec5SDimitry Andric Printf("ALARM: working on the last Unit for %zd seconds\n", Seconds); 3010b57cec5SDimitry Andric Printf(" and the timeout value is %d (use -timeout=N to change)\n", 3020b57cec5SDimitry Andric Options.UnitTimeoutSec); 3030b57cec5SDimitry Andric DumpCurrentUnit("timeout-"); 3040b57cec5SDimitry Andric Printf("==%lu== ERROR: libFuzzer: timeout after %d seconds\n", GetPid(), 3050b57cec5SDimitry Andric Seconds); 3060b57cec5SDimitry Andric PrintStackTrace(); 3070b57cec5SDimitry Andric Printf("SUMMARY: libFuzzer: timeout\n"); 3080b57cec5SDimitry Andric PrintFinalStats(); 3090b57cec5SDimitry Andric _Exit(Options.TimeoutExitCode); // Stop right now. 3100b57cec5SDimitry Andric } 3110b57cec5SDimitry Andric } 3120b57cec5SDimitry Andric 3130b57cec5SDimitry Andric void Fuzzer::RssLimitCallback() { 3140b57cec5SDimitry Andric if (EF->__sanitizer_acquire_crash_state && 3150b57cec5SDimitry Andric !EF->__sanitizer_acquire_crash_state()) 3160b57cec5SDimitry Andric return; 3170b57cec5SDimitry Andric Printf( 3180b57cec5SDimitry Andric "==%lu== ERROR: libFuzzer: out-of-memory (used: %zdMb; limit: %zdMb)\n", 3190b57cec5SDimitry Andric GetPid(), GetPeakRSSMb(), Options.RssLimitMb); 3200b57cec5SDimitry Andric Printf(" To change the out-of-memory limit use -rss_limit_mb=<N>\n\n"); 3210b57cec5SDimitry Andric PrintMemoryProfile(); 3220b57cec5SDimitry Andric DumpCurrentUnit("oom-"); 3230b57cec5SDimitry Andric Printf("SUMMARY: libFuzzer: out-of-memory\n"); 3240b57cec5SDimitry Andric PrintFinalStats(); 3250b57cec5SDimitry Andric _Exit(Options.OOMExitCode); // Stop right now. 3260b57cec5SDimitry Andric } 3270b57cec5SDimitry Andric 32868d75effSDimitry Andric void Fuzzer::PrintStats(const char *Where, const char *End, size_t Units, 32968d75effSDimitry Andric size_t Features) { 3300b57cec5SDimitry Andric size_t ExecPerSec = execPerSec(); 3310b57cec5SDimitry Andric if (!Options.Verbosity) 3320b57cec5SDimitry Andric return; 3330b57cec5SDimitry Andric Printf("#%zd\t%s", TotalNumberOfRuns, Where); 3340b57cec5SDimitry Andric if (size_t N = TPC.GetTotalPCCoverage()) 3350b57cec5SDimitry Andric Printf(" cov: %zd", N); 33668d75effSDimitry Andric if (size_t N = Features ? Features : Corpus.NumFeatures()) 3370b57cec5SDimitry Andric Printf(" ft: %zd", N); 3380b57cec5SDimitry Andric if (!Corpus.empty()) { 3390b57cec5SDimitry Andric Printf(" corp: %zd", Corpus.NumActiveUnits()); 3400b57cec5SDimitry Andric if (size_t N = Corpus.SizeInBytes()) { 3410b57cec5SDimitry Andric if (N < (1 << 14)) 3420b57cec5SDimitry Andric Printf("/%zdb", N); 3430b57cec5SDimitry Andric else if (N < (1 << 24)) 3440b57cec5SDimitry Andric Printf("/%zdKb", N >> 10); 3450b57cec5SDimitry Andric else 3460b57cec5SDimitry Andric Printf("/%zdMb", N >> 20); 3470b57cec5SDimitry Andric } 3480b57cec5SDimitry Andric if (size_t FF = Corpus.NumInputsThatTouchFocusFunction()) 3490b57cec5SDimitry Andric Printf(" focus: %zd", FF); 3500b57cec5SDimitry Andric } 3510b57cec5SDimitry Andric if (TmpMaxMutationLen) 3520b57cec5SDimitry Andric Printf(" lim: %zd", TmpMaxMutationLen); 3530b57cec5SDimitry Andric if (Units) 3540b57cec5SDimitry Andric Printf(" units: %zd", Units); 3550b57cec5SDimitry Andric 3560b57cec5SDimitry Andric Printf(" exec/s: %zd", ExecPerSec); 3570b57cec5SDimitry Andric Printf(" rss: %zdMb", GetPeakRSSMb()); 3580b57cec5SDimitry Andric Printf("%s", End); 3590b57cec5SDimitry Andric } 3600b57cec5SDimitry Andric 3610b57cec5SDimitry Andric void Fuzzer::PrintFinalStats() { 362e8d8bef9SDimitry Andric if (Options.PrintFullCoverage) 363e8d8bef9SDimitry Andric TPC.PrintCoverage(/*PrintAllCounters=*/true); 3640b57cec5SDimitry Andric if (Options.PrintCoverage) 365e8d8bef9SDimitry Andric TPC.PrintCoverage(/*PrintAllCounters=*/false); 3660b57cec5SDimitry Andric if (Options.PrintCorpusStats) 3670b57cec5SDimitry Andric Corpus.PrintStats(); 3680b57cec5SDimitry Andric if (!Options.PrintFinalStats) 3690b57cec5SDimitry Andric return; 3700b57cec5SDimitry Andric size_t ExecPerSec = execPerSec(); 3710b57cec5SDimitry Andric Printf("stat::number_of_executed_units: %zd\n", TotalNumberOfRuns); 3720b57cec5SDimitry Andric Printf("stat::average_exec_per_sec: %zd\n", ExecPerSec); 3730b57cec5SDimitry Andric Printf("stat::new_units_added: %zd\n", NumberOfNewUnitsAdded); 3740b57cec5SDimitry Andric Printf("stat::slowest_unit_time_sec: %zd\n", TimeOfLongestUnitInSeconds); 3750b57cec5SDimitry Andric Printf("stat::peak_rss_mb: %zd\n", GetPeakRSSMb()); 3760b57cec5SDimitry Andric } 3770b57cec5SDimitry Andric 3780b57cec5SDimitry Andric void Fuzzer::SetMaxInputLen(size_t MaxInputLen) { 3790b57cec5SDimitry Andric assert(this->MaxInputLen == 0); // Can only reset MaxInputLen from 0 to non-0. 3800b57cec5SDimitry Andric assert(MaxInputLen); 3810b57cec5SDimitry Andric this->MaxInputLen = MaxInputLen; 3820b57cec5SDimitry Andric this->MaxMutationLen = MaxInputLen; 3830b57cec5SDimitry Andric AllocateCurrentUnitData(); 3840b57cec5SDimitry Andric Printf("INFO: -max_len is not provided; " 3850b57cec5SDimitry Andric "libFuzzer will not generate inputs larger than %zd bytes\n", 3860b57cec5SDimitry Andric MaxInputLen); 3870b57cec5SDimitry Andric } 3880b57cec5SDimitry Andric 3890b57cec5SDimitry Andric void Fuzzer::SetMaxMutationLen(size_t MaxMutationLen) { 3900b57cec5SDimitry Andric assert(MaxMutationLen && MaxMutationLen <= MaxInputLen); 3910b57cec5SDimitry Andric this->MaxMutationLen = MaxMutationLen; 3920b57cec5SDimitry Andric } 3930b57cec5SDimitry Andric 3940b57cec5SDimitry Andric void Fuzzer::CheckExitOnSrcPosOrItem() { 3950b57cec5SDimitry Andric if (!Options.ExitOnSrcPos.empty()) { 396349cc55cSDimitry Andric static auto *PCsSet = new std::set<uintptr_t>; 3970b57cec5SDimitry Andric auto HandlePC = [&](const TracePC::PCTableEntry *TE) { 3980b57cec5SDimitry Andric if (!PCsSet->insert(TE->PC).second) 3990b57cec5SDimitry Andric return; 4000b57cec5SDimitry Andric std::string Descr = DescribePC("%F %L", TE->PC + 1); 4010b57cec5SDimitry Andric if (Descr.find(Options.ExitOnSrcPos) != std::string::npos) { 4020b57cec5SDimitry Andric Printf("INFO: found line matching '%s', exiting.\n", 4030b57cec5SDimitry Andric Options.ExitOnSrcPos.c_str()); 4040b57cec5SDimitry Andric _Exit(0); 4050b57cec5SDimitry Andric } 4060b57cec5SDimitry Andric }; 4070b57cec5SDimitry Andric TPC.ForEachObservedPC(HandlePC); 4080b57cec5SDimitry Andric } 4090b57cec5SDimitry Andric if (!Options.ExitOnItem.empty()) { 4100b57cec5SDimitry Andric if (Corpus.HasUnit(Options.ExitOnItem)) { 4110b57cec5SDimitry Andric Printf("INFO: found item with checksum '%s', exiting.\n", 4120b57cec5SDimitry Andric Options.ExitOnItem.c_str()); 4130b57cec5SDimitry Andric _Exit(0); 4140b57cec5SDimitry Andric } 4150b57cec5SDimitry Andric } 4160b57cec5SDimitry Andric } 4170b57cec5SDimitry Andric 4180b57cec5SDimitry Andric void Fuzzer::RereadOutputCorpus(size_t MaxSize) { 4190b57cec5SDimitry Andric if (Options.OutputCorpus.empty() || !Options.ReloadIntervalSec) 4200b57cec5SDimitry Andric return; 421349cc55cSDimitry Andric std::vector<Unit> AdditionalCorpus; 422349cc55cSDimitry Andric std::vector<std::string> AdditionalCorpusPaths; 423fe6060f1SDimitry Andric ReadDirToVectorOfUnits( 424fe6060f1SDimitry Andric Options.OutputCorpus.c_str(), &AdditionalCorpus, 4250b57cec5SDimitry Andric &EpochOfLastReadOfOutputCorpus, MaxSize, 426fe6060f1SDimitry Andric /*ExitOnError*/ false, 427fe6060f1SDimitry Andric (Options.Verbosity >= 2 ? &AdditionalCorpusPaths : nullptr)); 4280b57cec5SDimitry Andric if (Options.Verbosity >= 2) 4290b57cec5SDimitry Andric Printf("Reload: read %zd new units.\n", AdditionalCorpus.size()); 4300b57cec5SDimitry Andric bool Reloaded = false; 431fe6060f1SDimitry Andric for (size_t i = 0; i != AdditionalCorpus.size(); ++i) { 432fe6060f1SDimitry Andric auto &U = AdditionalCorpus[i]; 4330b57cec5SDimitry Andric if (U.size() > MaxSize) 4340b57cec5SDimitry Andric U.resize(MaxSize); 4350b57cec5SDimitry Andric if (!Corpus.HasUnit(U)) { 4360b57cec5SDimitry Andric if (RunOne(U.data(), U.size())) { 4370b57cec5SDimitry Andric CheckExitOnSrcPosOrItem(); 4380b57cec5SDimitry Andric Reloaded = true; 439fe6060f1SDimitry Andric if (Options.Verbosity >= 2) 440fe6060f1SDimitry Andric Printf("Reloaded %s\n", AdditionalCorpusPaths[i].c_str()); 4410b57cec5SDimitry Andric } 4420b57cec5SDimitry Andric } 4430b57cec5SDimitry Andric } 4440b57cec5SDimitry Andric if (Reloaded) 4450b57cec5SDimitry Andric PrintStats("RELOAD"); 4460b57cec5SDimitry Andric } 4470b57cec5SDimitry Andric 4480b57cec5SDimitry Andric void Fuzzer::PrintPulseAndReportSlowInput(const uint8_t *Data, size_t Size) { 4490b57cec5SDimitry Andric auto TimeOfUnit = 4500b57cec5SDimitry Andric duration_cast<seconds>(UnitStopTime - UnitStartTime).count(); 4510b57cec5SDimitry Andric if (!(TotalNumberOfRuns & (TotalNumberOfRuns - 1)) && 4520b57cec5SDimitry Andric secondsSinceProcessStartUp() >= 2) 4530b57cec5SDimitry Andric PrintStats("pulse "); 454fe6060f1SDimitry Andric auto Threshhold = 455fe6060f1SDimitry Andric static_cast<long>(static_cast<double>(TimeOfLongestUnitInSeconds) * 1.1); 456fe6060f1SDimitry Andric if (TimeOfUnit > Threshhold && TimeOfUnit >= Options.ReportSlowUnits) { 4570b57cec5SDimitry Andric TimeOfLongestUnitInSeconds = TimeOfUnit; 4580b57cec5SDimitry Andric Printf("Slowest unit: %zd s:\n", TimeOfLongestUnitInSeconds); 4590b57cec5SDimitry Andric WriteUnitToFileWithPrefix({Data, Data + Size}, "slow-unit-"); 4600b57cec5SDimitry Andric } 4610b57cec5SDimitry Andric } 4620b57cec5SDimitry Andric 4630b57cec5SDimitry Andric static void WriteFeatureSetToFile(const std::string &FeaturesDir, 4640b57cec5SDimitry Andric const std::string &FileName, 465349cc55cSDimitry Andric const std::vector<uint32_t> &FeatureSet) { 4660b57cec5SDimitry Andric if (FeaturesDir.empty() || FeatureSet.empty()) return; 4670b57cec5SDimitry Andric WriteToFile(reinterpret_cast<const uint8_t *>(FeatureSet.data()), 4680b57cec5SDimitry Andric FeatureSet.size() * sizeof(FeatureSet[0]), 4690b57cec5SDimitry Andric DirPlusFile(FeaturesDir, FileName)); 4700b57cec5SDimitry Andric } 4710b57cec5SDimitry Andric 4720b57cec5SDimitry Andric static void RenameFeatureSetFile(const std::string &FeaturesDir, 4730b57cec5SDimitry Andric const std::string &OldFile, 4740b57cec5SDimitry Andric const std::string &NewFile) { 4750b57cec5SDimitry Andric if (FeaturesDir.empty()) return; 4760b57cec5SDimitry Andric RenameFile(DirPlusFile(FeaturesDir, OldFile), 4770b57cec5SDimitry Andric DirPlusFile(FeaturesDir, NewFile)); 4780b57cec5SDimitry Andric } 4790b57cec5SDimitry Andric 480e8d8bef9SDimitry Andric static void WriteEdgeToMutationGraphFile(const std::string &MutationGraphFile, 481e8d8bef9SDimitry Andric const InputInfo *II, 482e8d8bef9SDimitry Andric const InputInfo *BaseII, 483e8d8bef9SDimitry Andric const std::string &MS) { 484e8d8bef9SDimitry Andric if (MutationGraphFile.empty()) 485e8d8bef9SDimitry Andric return; 486e8d8bef9SDimitry Andric 487e8d8bef9SDimitry Andric std::string Sha1 = Sha1ToString(II->Sha1); 488e8d8bef9SDimitry Andric 489e8d8bef9SDimitry Andric std::string OutputString; 490e8d8bef9SDimitry Andric 491e8d8bef9SDimitry Andric // Add a new vertex. 492e8d8bef9SDimitry Andric OutputString.append("\""); 493e8d8bef9SDimitry Andric OutputString.append(Sha1); 494e8d8bef9SDimitry Andric OutputString.append("\"\n"); 495e8d8bef9SDimitry Andric 496e8d8bef9SDimitry Andric // Add a new edge if there is base input. 497e8d8bef9SDimitry Andric if (BaseII) { 498e8d8bef9SDimitry Andric std::string BaseSha1 = Sha1ToString(BaseII->Sha1); 499e8d8bef9SDimitry Andric OutputString.append("\""); 500e8d8bef9SDimitry Andric OutputString.append(BaseSha1); 501e8d8bef9SDimitry Andric OutputString.append("\" -> \""); 502e8d8bef9SDimitry Andric OutputString.append(Sha1); 503e8d8bef9SDimitry Andric OutputString.append("\" [label=\""); 504e8d8bef9SDimitry Andric OutputString.append(MS); 505e8d8bef9SDimitry Andric OutputString.append("\"];\n"); 506e8d8bef9SDimitry Andric } 507e8d8bef9SDimitry Andric 508e8d8bef9SDimitry Andric AppendToFile(OutputString, MutationGraphFile); 509e8d8bef9SDimitry Andric } 510e8d8bef9SDimitry Andric 5110b57cec5SDimitry Andric bool Fuzzer::RunOne(const uint8_t *Data, size_t Size, bool MayDeleteFile, 512e8d8bef9SDimitry Andric InputInfo *II, bool ForceAddToCorpus, 513e8d8bef9SDimitry Andric bool *FoundUniqFeatures) { 5140b57cec5SDimitry Andric if (!Size) 5150b57cec5SDimitry Andric return false; 516fe6060f1SDimitry Andric // Largest input length should be INT_MAX. 517fe6060f1SDimitry Andric assert(Size < std::numeric_limits<uint32_t>::max()); 5180b57cec5SDimitry Andric 51981ad6265SDimitry Andric if(!ExecuteCallback(Data, Size)) return false; 520e8d8bef9SDimitry Andric auto TimeOfUnit = duration_cast<microseconds>(UnitStopTime - UnitStartTime); 5210b57cec5SDimitry Andric 5220b57cec5SDimitry Andric UniqFeatureSetTmp.clear(); 5230b57cec5SDimitry Andric size_t FoundUniqFeaturesOfII = 0; 5240b57cec5SDimitry Andric size_t NumUpdatesBefore = Corpus.NumFeatureUpdates(); 525fe6060f1SDimitry Andric TPC.CollectFeatures([&](uint32_t Feature) { 526fe6060f1SDimitry Andric if (Corpus.AddFeature(Feature, static_cast<uint32_t>(Size), Options.Shrink)) 5270b57cec5SDimitry Andric UniqFeatureSetTmp.push_back(Feature); 5285ffd83dbSDimitry Andric if (Options.Entropic) 5295ffd83dbSDimitry Andric Corpus.UpdateFeatureFrequency(II, Feature); 530e8d8bef9SDimitry Andric if (Options.ReduceInputs && II && !II->NeverReduce) 5310b57cec5SDimitry Andric if (std::binary_search(II->UniqFeatureSet.begin(), 5320b57cec5SDimitry Andric II->UniqFeatureSet.end(), Feature)) 5330b57cec5SDimitry Andric FoundUniqFeaturesOfII++; 5340b57cec5SDimitry Andric }); 5350b57cec5SDimitry Andric if (FoundUniqFeatures) 5360b57cec5SDimitry Andric *FoundUniqFeatures = FoundUniqFeaturesOfII; 5370b57cec5SDimitry Andric PrintPulseAndReportSlowInput(Data, Size); 5380b57cec5SDimitry Andric size_t NumNewFeatures = Corpus.NumFeatureUpdates() - NumUpdatesBefore; 539e8d8bef9SDimitry Andric if (NumNewFeatures || ForceAddToCorpus) { 5400b57cec5SDimitry Andric TPC.UpdateObservedPCs(); 541e8d8bef9SDimitry Andric auto NewII = 542e8d8bef9SDimitry Andric Corpus.AddToCorpus({Data, Data + Size}, NumNewFeatures, MayDeleteFile, 543e8d8bef9SDimitry Andric TPC.ObservedFocusFunction(), ForceAddToCorpus, 544e8d8bef9SDimitry Andric TimeOfUnit, UniqFeatureSetTmp, DFT, II); 5450b57cec5SDimitry Andric WriteFeatureSetToFile(Options.FeaturesDir, Sha1ToString(NewII->Sha1), 5460b57cec5SDimitry Andric NewII->UniqFeatureSet); 547e8d8bef9SDimitry Andric WriteEdgeToMutationGraphFile(Options.MutationGraphFile, NewII, II, 548e8d8bef9SDimitry Andric MD.MutationSequence()); 5490b57cec5SDimitry Andric return true; 5500b57cec5SDimitry Andric } 5510b57cec5SDimitry Andric if (II && FoundUniqFeaturesOfII && 5520b57cec5SDimitry Andric II->DataFlowTraceForFocusFunction.empty() && 5530b57cec5SDimitry Andric FoundUniqFeaturesOfII == II->UniqFeatureSet.size() && 5540b57cec5SDimitry Andric II->U.size() > Size) { 5550b57cec5SDimitry Andric auto OldFeaturesFile = Sha1ToString(II->Sha1); 556349cc55cSDimitry Andric Corpus.Replace(II, {Data, Data + Size}, TimeOfUnit); 5570b57cec5SDimitry Andric RenameFeatureSetFile(Options.FeaturesDir, OldFeaturesFile, 5580b57cec5SDimitry Andric Sha1ToString(II->Sha1)); 5590b57cec5SDimitry Andric return true; 5600b57cec5SDimitry Andric } 5610b57cec5SDimitry Andric return false; 5620b57cec5SDimitry Andric } 5630b57cec5SDimitry Andric 564e8d8bef9SDimitry Andric void Fuzzer::TPCUpdateObservedPCs() { TPC.UpdateObservedPCs(); } 565e8d8bef9SDimitry Andric 5660b57cec5SDimitry Andric size_t Fuzzer::GetCurrentUnitInFuzzingThead(const uint8_t **Data) const { 5670b57cec5SDimitry Andric assert(InFuzzingThread()); 5680b57cec5SDimitry Andric *Data = CurrentUnitData; 5690b57cec5SDimitry Andric return CurrentUnitSize; 5700b57cec5SDimitry Andric } 5710b57cec5SDimitry Andric 5720b57cec5SDimitry Andric void Fuzzer::CrashOnOverwrittenData() { 57368d75effSDimitry Andric Printf("==%d== ERROR: libFuzzer: fuzz target overwrites its const input\n", 5740b57cec5SDimitry Andric GetPid()); 57568d75effSDimitry Andric PrintStackTrace(); 57668d75effSDimitry Andric Printf("SUMMARY: libFuzzer: overwrites-const-input\n"); 5770b57cec5SDimitry Andric DumpCurrentUnit("crash-"); 57868d75effSDimitry Andric PrintFinalStats(); 5790b57cec5SDimitry Andric _Exit(Options.ErrorExitCode); // Stop right now. 5800b57cec5SDimitry Andric } 5810b57cec5SDimitry Andric 5820b57cec5SDimitry Andric // Compare two arrays, but not all bytes if the arrays are large. 5830b57cec5SDimitry Andric static bool LooseMemeq(const uint8_t *A, const uint8_t *B, size_t Size) { 5840b57cec5SDimitry Andric const size_t Limit = 64; 5850b57cec5SDimitry Andric if (Size <= 64) 5860b57cec5SDimitry Andric return !memcmp(A, B, Size); 5870b57cec5SDimitry Andric // Compare first and last Limit/2 bytes. 5880b57cec5SDimitry Andric return !memcmp(A, B, Limit / 2) && 5890b57cec5SDimitry Andric !memcmp(A + Size - Limit / 2, B + Size - Limit / 2, Limit / 2); 5900b57cec5SDimitry Andric } 5910b57cec5SDimitry Andric 592fe6060f1SDimitry Andric // This method is not inlined because it would cause a test to fail where it 593fe6060f1SDimitry Andric // is part of the stack unwinding. See D97975 for details. 59481ad6265SDimitry Andric ATTRIBUTE_NOINLINE bool Fuzzer::ExecuteCallback(const uint8_t *Data, 595fe6060f1SDimitry Andric size_t Size) { 5960b57cec5SDimitry Andric TPC.RecordInitialStack(); 5970b57cec5SDimitry Andric TotalNumberOfRuns++; 5980b57cec5SDimitry Andric assert(InFuzzingThread()); 5990b57cec5SDimitry Andric // We copy the contents of Unit into a separate heap buffer 6000b57cec5SDimitry Andric // so that we reliably find buffer overflows in it. 6010b57cec5SDimitry Andric uint8_t *DataCopy = new uint8_t[Size]; 6020b57cec5SDimitry Andric memcpy(DataCopy, Data, Size); 6030b57cec5SDimitry Andric if (EF->__msan_unpoison) 6040b57cec5SDimitry Andric EF->__msan_unpoison(DataCopy, Size); 6050b57cec5SDimitry Andric if (EF->__msan_unpoison_param) 6060b57cec5SDimitry Andric EF->__msan_unpoison_param(2); 6070b57cec5SDimitry Andric if (CurrentUnitData && CurrentUnitData != Data) 6080b57cec5SDimitry Andric memcpy(CurrentUnitData, Data, Size); 6090b57cec5SDimitry Andric CurrentUnitSize = Size; 61081ad6265SDimitry Andric int CBRes = 0; 6110b57cec5SDimitry Andric { 6120b57cec5SDimitry Andric ScopedEnableMsanInterceptorChecks S; 6130b57cec5SDimitry Andric AllocTracer.Start(Options.TraceMalloc); 6140b57cec5SDimitry Andric UnitStartTime = system_clock::now(); 6150b57cec5SDimitry Andric TPC.ResetMaps(); 6160b57cec5SDimitry Andric RunningUserCallback = true; 61781ad6265SDimitry Andric CBRes = CB(DataCopy, Size); 6180b57cec5SDimitry Andric RunningUserCallback = false; 6190b57cec5SDimitry Andric UnitStopTime = system_clock::now(); 62081ad6265SDimitry Andric assert(CBRes == 0 || CBRes == -1); 6210b57cec5SDimitry Andric HasMoreMallocsThanFrees = AllocTracer.Stop(); 6220b57cec5SDimitry Andric } 6230b57cec5SDimitry Andric if (!LooseMemeq(DataCopy, Data, Size)) 6240b57cec5SDimitry Andric CrashOnOverwrittenData(); 6250b57cec5SDimitry Andric CurrentUnitSize = 0; 6260b57cec5SDimitry Andric delete[] DataCopy; 62781ad6265SDimitry Andric return CBRes == 0; 6280b57cec5SDimitry Andric } 6290b57cec5SDimitry Andric 6300b57cec5SDimitry Andric std::string Fuzzer::WriteToOutputCorpus(const Unit &U) { 6310b57cec5SDimitry Andric if (Options.OnlyASCII) 6320b57cec5SDimitry Andric assert(IsASCII(U)); 6330b57cec5SDimitry Andric if (Options.OutputCorpus.empty()) 6340b57cec5SDimitry Andric return ""; 6350b57cec5SDimitry Andric std::string Path = DirPlusFile(Options.OutputCorpus, Hash(U)); 6360b57cec5SDimitry Andric WriteToFile(U, Path); 6370b57cec5SDimitry Andric if (Options.Verbosity >= 2) 6380b57cec5SDimitry Andric Printf("Written %zd bytes to %s\n", U.size(), Path.c_str()); 6390b57cec5SDimitry Andric return Path; 6400b57cec5SDimitry Andric } 6410b57cec5SDimitry Andric 6420b57cec5SDimitry Andric void Fuzzer::WriteUnitToFileWithPrefix(const Unit &U, const char *Prefix) { 6430b57cec5SDimitry Andric if (!Options.SaveArtifacts) 6440b57cec5SDimitry Andric return; 6450b57cec5SDimitry Andric std::string Path = Options.ArtifactPrefix + Prefix + Hash(U); 6460b57cec5SDimitry Andric if (!Options.ExactArtifactPath.empty()) 6470b57cec5SDimitry Andric Path = Options.ExactArtifactPath; // Overrides ArtifactPrefix. 6480b57cec5SDimitry Andric WriteToFile(U, Path); 6490b57cec5SDimitry Andric Printf("artifact_prefix='%s'; Test unit written to %s\n", 6500b57cec5SDimitry Andric Options.ArtifactPrefix.c_str(), Path.c_str()); 6510b57cec5SDimitry Andric if (U.size() <= kMaxUnitSizeToPrint) 6520b57cec5SDimitry Andric Printf("Base64: %s\n", Base64(U).c_str()); 6530b57cec5SDimitry Andric } 6540b57cec5SDimitry Andric 6550b57cec5SDimitry Andric void Fuzzer::PrintStatusForNewUnit(const Unit &U, const char *Text) { 6560b57cec5SDimitry Andric if (!Options.PrintNEW) 6570b57cec5SDimitry Andric return; 6580b57cec5SDimitry Andric PrintStats(Text, ""); 6590b57cec5SDimitry Andric if (Options.Verbosity) { 6600b57cec5SDimitry Andric Printf(" L: %zd/%zd ", U.size(), Corpus.MaxInputSize()); 661e8d8bef9SDimitry Andric MD.PrintMutationSequence(Options.Verbosity >= 2); 6620b57cec5SDimitry Andric Printf("\n"); 6630b57cec5SDimitry Andric } 6640b57cec5SDimitry Andric } 6650b57cec5SDimitry Andric 6660b57cec5SDimitry Andric void Fuzzer::ReportNewCoverage(InputInfo *II, const Unit &U) { 6670b57cec5SDimitry Andric II->NumSuccessfullMutations++; 6680b57cec5SDimitry Andric MD.RecordSuccessfulMutationSequence(); 6690b57cec5SDimitry Andric PrintStatusForNewUnit(U, II->Reduced ? "REDUCE" : "NEW "); 6700b57cec5SDimitry Andric WriteToOutputCorpus(U); 6710b57cec5SDimitry Andric NumberOfNewUnitsAdded++; 6720b57cec5SDimitry Andric CheckExitOnSrcPosOrItem(); // Check only after the unit is saved to corpus. 6730b57cec5SDimitry Andric LastCorpusUpdateRun = TotalNumberOfRuns; 6740b57cec5SDimitry Andric } 6750b57cec5SDimitry Andric 6760b57cec5SDimitry Andric // Tries detecting a memory leak on the particular input that we have just 6770b57cec5SDimitry Andric // executed before calling this function. 6780b57cec5SDimitry Andric void Fuzzer::TryDetectingAMemoryLeak(const uint8_t *Data, size_t Size, 6790b57cec5SDimitry Andric bool DuringInitialCorpusExecution) { 6800b57cec5SDimitry Andric if (!HasMoreMallocsThanFrees) 6810b57cec5SDimitry Andric return; // mallocs==frees, a leak is unlikely. 6820b57cec5SDimitry Andric if (!Options.DetectLeaks) 6830b57cec5SDimitry Andric return; 6840b57cec5SDimitry Andric if (!DuringInitialCorpusExecution && 6850b57cec5SDimitry Andric TotalNumberOfRuns >= Options.MaxNumberOfRuns) 6860b57cec5SDimitry Andric return; 6870b57cec5SDimitry Andric if (!&(EF->__lsan_enable) || !&(EF->__lsan_disable) || 6880b57cec5SDimitry Andric !(EF->__lsan_do_recoverable_leak_check)) 6890b57cec5SDimitry Andric return; // No lsan. 6900b57cec5SDimitry Andric // Run the target once again, but with lsan disabled so that if there is 6910b57cec5SDimitry Andric // a real leak we do not report it twice. 6920b57cec5SDimitry Andric EF->__lsan_disable(); 6930b57cec5SDimitry Andric ExecuteCallback(Data, Size); 6940b57cec5SDimitry Andric EF->__lsan_enable(); 6950b57cec5SDimitry Andric if (!HasMoreMallocsThanFrees) 6960b57cec5SDimitry Andric return; // a leak is unlikely. 6970b57cec5SDimitry Andric if (NumberOfLeakDetectionAttempts++ > 1000) { 6980b57cec5SDimitry Andric Options.DetectLeaks = false; 6990b57cec5SDimitry Andric Printf("INFO: libFuzzer disabled leak detection after every mutation.\n" 7000b57cec5SDimitry Andric " Most likely the target function accumulates allocated\n" 7010b57cec5SDimitry Andric " memory in a global state w/o actually leaking it.\n" 7020b57cec5SDimitry Andric " You may try running this binary with -trace_malloc=[12]" 7030b57cec5SDimitry Andric " to get a trace of mallocs and frees.\n" 7040b57cec5SDimitry Andric " If LeakSanitizer is enabled in this process it will still\n" 7050b57cec5SDimitry Andric " run on the process shutdown.\n"); 7060b57cec5SDimitry Andric return; 7070b57cec5SDimitry Andric } 7080b57cec5SDimitry Andric // Now perform the actual lsan pass. This is expensive and we must ensure 7090b57cec5SDimitry Andric // we don't call it too often. 7100b57cec5SDimitry Andric if (EF->__lsan_do_recoverable_leak_check()) { // Leak is found, report it. 7110b57cec5SDimitry Andric if (DuringInitialCorpusExecution) 7120b57cec5SDimitry Andric Printf("\nINFO: a leak has been found in the initial corpus.\n\n"); 7130b57cec5SDimitry Andric Printf("INFO: to ignore leaks on libFuzzer side use -detect_leaks=0.\n\n"); 7140b57cec5SDimitry Andric CurrentUnitSize = Size; 7150b57cec5SDimitry Andric DumpCurrentUnit("leak-"); 7160b57cec5SDimitry Andric PrintFinalStats(); 7170b57cec5SDimitry Andric _Exit(Options.ErrorExitCode); // not exit() to disable lsan further on. 7180b57cec5SDimitry Andric } 7190b57cec5SDimitry Andric } 7200b57cec5SDimitry Andric 7210b57cec5SDimitry Andric void Fuzzer::MutateAndTestOne() { 7220b57cec5SDimitry Andric MD.StartMutationSequence(); 7230b57cec5SDimitry Andric 7240b57cec5SDimitry Andric auto &II = Corpus.ChooseUnitToMutate(MD.GetRand()); 725e8d8bef9SDimitry Andric if (Options.DoCrossOver) { 726e8d8bef9SDimitry Andric auto &CrossOverII = Corpus.ChooseUnitToCrossOverWith( 727e8d8bef9SDimitry Andric MD.GetRand(), Options.CrossOverUniformDist); 728e8d8bef9SDimitry Andric MD.SetCrossOverWith(&CrossOverII.U); 729e8d8bef9SDimitry Andric } 7300b57cec5SDimitry Andric const auto &U = II.U; 7310b57cec5SDimitry Andric memcpy(BaseSha1, II.Sha1, sizeof(BaseSha1)); 7320b57cec5SDimitry Andric assert(CurrentUnitData); 7330b57cec5SDimitry Andric size_t Size = U.size(); 7340b57cec5SDimitry Andric assert(Size <= MaxInputLen && "Oversized Unit"); 7350b57cec5SDimitry Andric memcpy(CurrentUnitData, U.data(), Size); 7360b57cec5SDimitry Andric 7370b57cec5SDimitry Andric assert(MaxMutationLen > 0); 7380b57cec5SDimitry Andric 7390b57cec5SDimitry Andric size_t CurrentMaxMutationLen = 7400b57cec5SDimitry Andric Min(MaxMutationLen, Max(U.size(), TmpMaxMutationLen)); 7410b57cec5SDimitry Andric assert(CurrentMaxMutationLen > 0); 7420b57cec5SDimitry Andric 7430b57cec5SDimitry Andric for (int i = 0; i < Options.MutateDepth; i++) { 7440b57cec5SDimitry Andric if (TotalNumberOfRuns >= Options.MaxNumberOfRuns) 7450b57cec5SDimitry Andric break; 7460b57cec5SDimitry Andric MaybeExitGracefully(); 7470b57cec5SDimitry Andric size_t NewSize = 0; 7480b57cec5SDimitry Andric if (II.HasFocusFunction && !II.DataFlowTraceForFocusFunction.empty() && 7490b57cec5SDimitry Andric Size <= CurrentMaxMutationLen) 7500b57cec5SDimitry Andric NewSize = MD.MutateWithMask(CurrentUnitData, Size, Size, 7510b57cec5SDimitry Andric II.DataFlowTraceForFocusFunction); 7520b57cec5SDimitry Andric 7530b57cec5SDimitry Andric // If MutateWithMask either failed or wasn't called, call default Mutate. 7540b57cec5SDimitry Andric if (!NewSize) 7550b57cec5SDimitry Andric NewSize = MD.Mutate(CurrentUnitData, Size, CurrentMaxMutationLen); 7560b57cec5SDimitry Andric assert(NewSize > 0 && "Mutator returned empty unit"); 7570b57cec5SDimitry Andric assert(NewSize <= CurrentMaxMutationLen && "Mutator return oversized unit"); 7580b57cec5SDimitry Andric Size = NewSize; 7590b57cec5SDimitry Andric II.NumExecutedMutations++; 7605ffd83dbSDimitry Andric Corpus.IncrementNumExecutedMutations(); 7610b57cec5SDimitry Andric 7620b57cec5SDimitry Andric bool FoundUniqFeatures = false; 7630b57cec5SDimitry Andric bool NewCov = RunOne(CurrentUnitData, Size, /*MayDeleteFile=*/true, &II, 764e8d8bef9SDimitry Andric /*ForceAddToCorpus*/ false, &FoundUniqFeatures); 7650b57cec5SDimitry Andric TryDetectingAMemoryLeak(CurrentUnitData, Size, 7660b57cec5SDimitry Andric /*DuringInitialCorpusExecution*/ false); 7670b57cec5SDimitry Andric if (NewCov) { 7680b57cec5SDimitry Andric ReportNewCoverage(&II, {CurrentUnitData, CurrentUnitData + Size}); 7690b57cec5SDimitry Andric break; // We will mutate this input more in the next rounds. 7700b57cec5SDimitry Andric } 7710b57cec5SDimitry Andric if (Options.ReduceDepth && !FoundUniqFeatures) 7720b57cec5SDimitry Andric break; 7730b57cec5SDimitry Andric } 7745ffd83dbSDimitry Andric 7755ffd83dbSDimitry Andric II.NeedsEnergyUpdate = true; 7760b57cec5SDimitry Andric } 7770b57cec5SDimitry Andric 7780b57cec5SDimitry Andric void Fuzzer::PurgeAllocator() { 7790b57cec5SDimitry Andric if (Options.PurgeAllocatorIntervalSec < 0 || !EF->__sanitizer_purge_allocator) 7800b57cec5SDimitry Andric return; 7810b57cec5SDimitry Andric if (duration_cast<seconds>(system_clock::now() - 7820b57cec5SDimitry Andric LastAllocatorPurgeAttemptTime) 7830b57cec5SDimitry Andric .count() < Options.PurgeAllocatorIntervalSec) 7840b57cec5SDimitry Andric return; 7850b57cec5SDimitry Andric 7860b57cec5SDimitry Andric if (Options.RssLimitMb <= 0 || 7870b57cec5SDimitry Andric GetPeakRSSMb() > static_cast<size_t>(Options.RssLimitMb) / 2) 7880b57cec5SDimitry Andric EF->__sanitizer_purge_allocator(); 7890b57cec5SDimitry Andric 7900b57cec5SDimitry Andric LastAllocatorPurgeAttemptTime = system_clock::now(); 7910b57cec5SDimitry Andric } 7920b57cec5SDimitry Andric 793349cc55cSDimitry Andric void Fuzzer::ReadAndExecuteSeedCorpora(std::vector<SizedFile> &CorporaFiles) { 7940b57cec5SDimitry Andric const size_t kMaxSaneLen = 1 << 20; 7950b57cec5SDimitry Andric const size_t kMinDefaultLen = 4096; 7960b57cec5SDimitry Andric size_t MaxSize = 0; 7970b57cec5SDimitry Andric size_t MinSize = -1; 7980b57cec5SDimitry Andric size_t TotalSize = 0; 7990b57cec5SDimitry Andric for (auto &File : CorporaFiles) { 8000b57cec5SDimitry Andric MaxSize = Max(File.Size, MaxSize); 8010b57cec5SDimitry Andric MinSize = Min(File.Size, MinSize); 8020b57cec5SDimitry Andric TotalSize += File.Size; 8030b57cec5SDimitry Andric } 8040b57cec5SDimitry Andric if (Options.MaxLen == 0) 8050b57cec5SDimitry Andric SetMaxInputLen(std::min(std::max(kMinDefaultLen, MaxSize), kMaxSaneLen)); 8060b57cec5SDimitry Andric assert(MaxInputLen > 0); 8070b57cec5SDimitry Andric 8080b57cec5SDimitry Andric // Test the callback with empty input and never try it again. 8090b57cec5SDimitry Andric uint8_t dummy = 0; 8100b57cec5SDimitry Andric ExecuteCallback(&dummy, 0); 8110b57cec5SDimitry Andric 8120b57cec5SDimitry Andric if (CorporaFiles.empty()) { 8130b57cec5SDimitry Andric Printf("INFO: A corpus is not provided, starting from an empty corpus\n"); 8140b57cec5SDimitry Andric Unit U({'\n'}); // Valid ASCII input. 8150b57cec5SDimitry Andric RunOne(U.data(), U.size()); 8160b57cec5SDimitry Andric } else { 8170b57cec5SDimitry Andric Printf("INFO: seed corpus: files: %zd min: %zdb max: %zdb total: %zdb" 8180b57cec5SDimitry Andric " rss: %zdMb\n", 8190b57cec5SDimitry Andric CorporaFiles.size(), MinSize, MaxSize, TotalSize, GetPeakRSSMb()); 8200b57cec5SDimitry Andric if (Options.ShuffleAtStartUp) 8210b57cec5SDimitry Andric std::shuffle(CorporaFiles.begin(), CorporaFiles.end(), MD.GetRand()); 8220b57cec5SDimitry Andric 8230b57cec5SDimitry Andric if (Options.PreferSmall) { 8240b57cec5SDimitry Andric std::stable_sort(CorporaFiles.begin(), CorporaFiles.end()); 8250b57cec5SDimitry Andric assert(CorporaFiles.front().Size <= CorporaFiles.back().Size); 8260b57cec5SDimitry Andric } 8270b57cec5SDimitry Andric 8280b57cec5SDimitry Andric // Load and execute inputs one by one. 8290b57cec5SDimitry Andric for (auto &SF : CorporaFiles) { 8300b57cec5SDimitry Andric auto U = FileToVector(SF.File, MaxInputLen, /*ExitOnError=*/false); 8310b57cec5SDimitry Andric assert(U.size() <= MaxInputLen); 832e8d8bef9SDimitry Andric RunOne(U.data(), U.size(), /*MayDeleteFile*/ false, /*II*/ nullptr, 833e8d8bef9SDimitry Andric /*ForceAddToCorpus*/ Options.KeepSeed, 834e8d8bef9SDimitry Andric /*FoundUniqFeatures*/ nullptr); 8350b57cec5SDimitry Andric CheckExitOnSrcPosOrItem(); 8360b57cec5SDimitry Andric TryDetectingAMemoryLeak(U.data(), U.size(), 8370b57cec5SDimitry Andric /*DuringInitialCorpusExecution*/ true); 8380b57cec5SDimitry Andric } 8390b57cec5SDimitry Andric } 8400b57cec5SDimitry Andric 8410b57cec5SDimitry Andric PrintStats("INITED"); 8425ffd83dbSDimitry Andric if (!Options.FocusFunction.empty()) { 8430b57cec5SDimitry Andric Printf("INFO: %zd/%zd inputs touch the focus function\n", 8440b57cec5SDimitry Andric Corpus.NumInputsThatTouchFocusFunction(), Corpus.size()); 8450b57cec5SDimitry Andric if (!Options.DataFlowTrace.empty()) 8460b57cec5SDimitry Andric Printf("INFO: %zd/%zd inputs have the Data Flow Trace\n", 8475ffd83dbSDimitry Andric Corpus.NumInputsWithDataFlowTrace(), 8485ffd83dbSDimitry Andric Corpus.NumInputsThatTouchFocusFunction()); 8495ffd83dbSDimitry Andric } 8500b57cec5SDimitry Andric 8510b57cec5SDimitry Andric if (Corpus.empty() && Options.MaxNumberOfRuns) { 85281ad6265SDimitry Andric Printf("WARNING: no interesting inputs were found so far. " 85381ad6265SDimitry Andric "Is the code instrumented for coverage?\n" 85481ad6265SDimitry Andric "This may also happen if the target rejected all inputs we tried so " 85581ad6265SDimitry Andric "far\n"); 85681ad6265SDimitry Andric // The remaining logic requires that the corpus is not empty, 85781ad6265SDimitry Andric // so we add one fake input to the in-memory corpus. 85881ad6265SDimitry Andric Corpus.AddToCorpus({'\n'}, /*NumFeatures=*/1, /*MayDeleteFile=*/true, 85981ad6265SDimitry Andric /*HasFocusFunction=*/false, /*NeverReduce=*/false, 86081ad6265SDimitry Andric /*TimeOfUnit=*/duration_cast<microseconds>(0s), {0}, DFT, 86181ad6265SDimitry Andric /*BaseII*/ nullptr); 8620b57cec5SDimitry Andric } 8630b57cec5SDimitry Andric } 8640b57cec5SDimitry Andric 865349cc55cSDimitry Andric void Fuzzer::Loop(std::vector<SizedFile> &CorporaFiles) { 8660b57cec5SDimitry Andric auto FocusFunctionOrAuto = Options.FocusFunction; 8670b57cec5SDimitry Andric DFT.Init(Options.DataFlowTrace, &FocusFunctionOrAuto, CorporaFiles, 8680b57cec5SDimitry Andric MD.GetRand()); 8690b57cec5SDimitry Andric TPC.SetFocusFunction(FocusFunctionOrAuto); 8700b57cec5SDimitry Andric ReadAndExecuteSeedCorpora(CorporaFiles); 8710b57cec5SDimitry Andric DFT.Clear(); // No need for DFT any more. 8720b57cec5SDimitry Andric TPC.SetPrintNewPCs(Options.PrintNewCovPcs); 8730b57cec5SDimitry Andric TPC.SetPrintNewFuncs(Options.PrintNewCovFuncs); 8740b57cec5SDimitry Andric system_clock::time_point LastCorpusReload = system_clock::now(); 8750b57cec5SDimitry Andric 8760b57cec5SDimitry Andric TmpMaxMutationLen = 8770b57cec5SDimitry Andric Min(MaxMutationLen, Max(size_t(4), Corpus.MaxInputSize())); 8780b57cec5SDimitry Andric 8790b57cec5SDimitry Andric while (true) { 8800b57cec5SDimitry Andric auto Now = system_clock::now(); 8810b57cec5SDimitry Andric if (!Options.StopFile.empty() && 8820b57cec5SDimitry Andric !FileToVector(Options.StopFile, 1, false).empty()) 8830b57cec5SDimitry Andric break; 8840b57cec5SDimitry Andric if (duration_cast<seconds>(Now - LastCorpusReload).count() >= 8850b57cec5SDimitry Andric Options.ReloadIntervalSec) { 8860b57cec5SDimitry Andric RereadOutputCorpus(MaxInputLen); 8870b57cec5SDimitry Andric LastCorpusReload = system_clock::now(); 8880b57cec5SDimitry Andric } 8890b57cec5SDimitry Andric if (TotalNumberOfRuns >= Options.MaxNumberOfRuns) 8900b57cec5SDimitry Andric break; 8910b57cec5SDimitry Andric if (TimedOut()) 8920b57cec5SDimitry Andric break; 8930b57cec5SDimitry Andric 8940b57cec5SDimitry Andric // Update TmpMaxMutationLen 8950b57cec5SDimitry Andric if (Options.LenControl) { 8960b57cec5SDimitry Andric if (TmpMaxMutationLen < MaxMutationLen && 8970b57cec5SDimitry Andric TotalNumberOfRuns - LastCorpusUpdateRun > 8980b57cec5SDimitry Andric Options.LenControl * Log(TmpMaxMutationLen)) { 8990b57cec5SDimitry Andric TmpMaxMutationLen = 9000b57cec5SDimitry Andric Min(MaxMutationLen, TmpMaxMutationLen + Log(TmpMaxMutationLen)); 9010b57cec5SDimitry Andric LastCorpusUpdateRun = TotalNumberOfRuns; 9020b57cec5SDimitry Andric } 9030b57cec5SDimitry Andric } else { 9040b57cec5SDimitry Andric TmpMaxMutationLen = MaxMutationLen; 9050b57cec5SDimitry Andric } 9060b57cec5SDimitry Andric 9070b57cec5SDimitry Andric // Perform several mutations and runs. 9080b57cec5SDimitry Andric MutateAndTestOne(); 9090b57cec5SDimitry Andric 9100b57cec5SDimitry Andric PurgeAllocator(); 9110b57cec5SDimitry Andric } 9120b57cec5SDimitry Andric 9130b57cec5SDimitry Andric PrintStats("DONE ", "\n"); 9140b57cec5SDimitry Andric MD.PrintRecommendedDictionary(); 9150b57cec5SDimitry Andric } 9160b57cec5SDimitry Andric 9170b57cec5SDimitry Andric void Fuzzer::MinimizeCrashLoop(const Unit &U) { 9180b57cec5SDimitry Andric if (U.size() <= 1) 9190b57cec5SDimitry Andric return; 9200b57cec5SDimitry Andric while (!TimedOut() && TotalNumberOfRuns < Options.MaxNumberOfRuns) { 9210b57cec5SDimitry Andric MD.StartMutationSequence(); 9220b57cec5SDimitry Andric memcpy(CurrentUnitData, U.data(), U.size()); 9230b57cec5SDimitry Andric for (int i = 0; i < Options.MutateDepth; i++) { 9240b57cec5SDimitry Andric size_t NewSize = MD.Mutate(CurrentUnitData, U.size(), MaxMutationLen); 9250b57cec5SDimitry Andric assert(NewSize > 0 && NewSize <= MaxMutationLen); 9260b57cec5SDimitry Andric ExecuteCallback(CurrentUnitData, NewSize); 9270b57cec5SDimitry Andric PrintPulseAndReportSlowInput(CurrentUnitData, NewSize); 9280b57cec5SDimitry Andric TryDetectingAMemoryLeak(CurrentUnitData, NewSize, 9290b57cec5SDimitry Andric /*DuringInitialCorpusExecution*/ false); 9300b57cec5SDimitry Andric } 9310b57cec5SDimitry Andric } 9320b57cec5SDimitry Andric } 9330b57cec5SDimitry Andric 9340b57cec5SDimitry Andric } // namespace fuzzer 9350b57cec5SDimitry Andric 9360b57cec5SDimitry Andric extern "C" { 9370b57cec5SDimitry Andric 9380b57cec5SDimitry Andric ATTRIBUTE_INTERFACE size_t 9390b57cec5SDimitry Andric LLVMFuzzerMutate(uint8_t *Data, size_t Size, size_t MaxSize) { 9400b57cec5SDimitry Andric assert(fuzzer::F); 9410b57cec5SDimitry Andric return fuzzer::F->GetMD().DefaultMutate(Data, Size, MaxSize); 9420b57cec5SDimitry Andric } 9430b57cec5SDimitry Andric 9440b57cec5SDimitry Andric } // extern "C" 945