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, 13906c3fb27SDimitry Andric const 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 void Fuzzer::AllocateCurrentUnitData() { 1640b57cec5SDimitry Andric if (CurrentUnitData || MaxInputLen == 0) 1650b57cec5SDimitry Andric return; 1660b57cec5SDimitry Andric CurrentUnitData = new uint8_t[MaxInputLen]; 1670b57cec5SDimitry Andric } 1680b57cec5SDimitry Andric 1690b57cec5SDimitry Andric void Fuzzer::StaticDeathCallback() { 1700b57cec5SDimitry Andric assert(F); 1710b57cec5SDimitry Andric F->DeathCallback(); 1720b57cec5SDimitry Andric } 1730b57cec5SDimitry Andric 1740b57cec5SDimitry Andric void Fuzzer::DumpCurrentUnit(const char *Prefix) { 1750b57cec5SDimitry Andric if (!CurrentUnitData) 1760b57cec5SDimitry Andric return; // Happens when running individual inputs. 1770b57cec5SDimitry Andric ScopedDisableMsanInterceptorChecks S; 1780b57cec5SDimitry Andric MD.PrintMutationSequence(); 1790b57cec5SDimitry Andric Printf("; base unit: %s\n", Sha1ToString(BaseSha1).c_str()); 1800b57cec5SDimitry Andric size_t UnitSize = CurrentUnitSize; 1810b57cec5SDimitry Andric if (UnitSize <= kMaxUnitSizeToPrint) { 1820b57cec5SDimitry Andric PrintHexArray(CurrentUnitData, UnitSize, "\n"); 1830b57cec5SDimitry Andric PrintASCII(CurrentUnitData, UnitSize, "\n"); 1840b57cec5SDimitry Andric } 1850b57cec5SDimitry Andric WriteUnitToFileWithPrefix({CurrentUnitData, CurrentUnitData + UnitSize}, 1860b57cec5SDimitry Andric Prefix); 1870b57cec5SDimitry Andric } 1880b57cec5SDimitry Andric 1890b57cec5SDimitry Andric NO_SANITIZE_MEMORY 1900b57cec5SDimitry Andric void Fuzzer::DeathCallback() { 1910b57cec5SDimitry Andric DumpCurrentUnit("crash-"); 1920b57cec5SDimitry Andric PrintFinalStats(); 1930b57cec5SDimitry Andric } 1940b57cec5SDimitry Andric 1950b57cec5SDimitry Andric void Fuzzer::StaticAlarmCallback() { 1960b57cec5SDimitry Andric assert(F); 1970b57cec5SDimitry Andric F->AlarmCallback(); 1980b57cec5SDimitry Andric } 1990b57cec5SDimitry Andric 2000b57cec5SDimitry Andric void Fuzzer::StaticCrashSignalCallback() { 2010b57cec5SDimitry Andric assert(F); 2020b57cec5SDimitry Andric F->CrashCallback(); 2030b57cec5SDimitry Andric } 2040b57cec5SDimitry Andric 2050b57cec5SDimitry Andric void Fuzzer::StaticExitCallback() { 2060b57cec5SDimitry Andric assert(F); 2070b57cec5SDimitry Andric F->ExitCallback(); 2080b57cec5SDimitry Andric } 2090b57cec5SDimitry Andric 2100b57cec5SDimitry Andric void Fuzzer::StaticInterruptCallback() { 2110b57cec5SDimitry Andric assert(F); 2120b57cec5SDimitry Andric F->InterruptCallback(); 2130b57cec5SDimitry Andric } 2140b57cec5SDimitry Andric 2150b57cec5SDimitry Andric void Fuzzer::StaticGracefulExitCallback() { 2160b57cec5SDimitry Andric assert(F); 2170b57cec5SDimitry Andric F->GracefulExitRequested = true; 2180b57cec5SDimitry Andric Printf("INFO: signal received, trying to exit gracefully\n"); 2190b57cec5SDimitry Andric } 2200b57cec5SDimitry Andric 2210b57cec5SDimitry Andric void Fuzzer::StaticFileSizeExceedCallback() { 2220b57cec5SDimitry Andric Printf("==%lu== ERROR: libFuzzer: file size exceeded\n", GetPid()); 2230b57cec5SDimitry Andric exit(1); 2240b57cec5SDimitry Andric } 2250b57cec5SDimitry Andric 2260b57cec5SDimitry Andric void Fuzzer::CrashCallback() { 2270b57cec5SDimitry Andric if (EF->__sanitizer_acquire_crash_state && 2280b57cec5SDimitry Andric !EF->__sanitizer_acquire_crash_state()) 2290b57cec5SDimitry Andric return; 2300b57cec5SDimitry Andric Printf("==%lu== ERROR: libFuzzer: deadly signal\n", GetPid()); 2310b57cec5SDimitry Andric PrintStackTrace(); 2320b57cec5SDimitry Andric Printf("NOTE: libFuzzer has rudimentary signal handlers.\n" 2330b57cec5SDimitry Andric " Combine libFuzzer with AddressSanitizer or similar for better " 2340b57cec5SDimitry Andric "crash reports.\n"); 2350b57cec5SDimitry Andric Printf("SUMMARY: libFuzzer: deadly signal\n"); 2360b57cec5SDimitry Andric DumpCurrentUnit("crash-"); 2370b57cec5SDimitry Andric PrintFinalStats(); 2380b57cec5SDimitry Andric _Exit(Options.ErrorExitCode); // Stop right now. 2390b57cec5SDimitry Andric } 2400b57cec5SDimitry Andric 2410b57cec5SDimitry Andric void Fuzzer::ExitCallback() { 2420b57cec5SDimitry Andric if (!RunningUserCallback) 2430b57cec5SDimitry Andric return; // This exit did not come from the user callback 2440b57cec5SDimitry Andric if (EF->__sanitizer_acquire_crash_state && 2450b57cec5SDimitry Andric !EF->__sanitizer_acquire_crash_state()) 2460b57cec5SDimitry Andric return; 2470b57cec5SDimitry Andric Printf("==%lu== ERROR: libFuzzer: fuzz target exited\n", GetPid()); 2480b57cec5SDimitry Andric PrintStackTrace(); 2490b57cec5SDimitry Andric Printf("SUMMARY: libFuzzer: fuzz target exited\n"); 2500b57cec5SDimitry Andric DumpCurrentUnit("crash-"); 2510b57cec5SDimitry Andric PrintFinalStats(); 2520b57cec5SDimitry Andric _Exit(Options.ErrorExitCode); 2530b57cec5SDimitry Andric } 2540b57cec5SDimitry Andric 2550b57cec5SDimitry Andric void Fuzzer::MaybeExitGracefully() { 2560b57cec5SDimitry Andric if (!F->GracefulExitRequested) return; 2570b57cec5SDimitry Andric Printf("==%lu== INFO: libFuzzer: exiting as requested\n", GetPid()); 2585ffd83dbSDimitry Andric RmDirRecursive(TempPath("FuzzWithFork", ".dir")); 2590b57cec5SDimitry Andric F->PrintFinalStats(); 2600b57cec5SDimitry Andric _Exit(0); 2610b57cec5SDimitry Andric } 2620b57cec5SDimitry Andric 263bdd1243dSDimitry Andric int Fuzzer::InterruptExitCode() { 264bdd1243dSDimitry Andric assert(F); 265bdd1243dSDimitry Andric return F->Options.InterruptExitCode; 266bdd1243dSDimitry Andric } 267bdd1243dSDimitry Andric 2680b57cec5SDimitry Andric void Fuzzer::InterruptCallback() { 2690b57cec5SDimitry Andric Printf("==%lu== libFuzzer: run interrupted; exiting\n", GetPid()); 2700b57cec5SDimitry Andric PrintFinalStats(); 2710b57cec5SDimitry Andric ScopedDisableMsanInterceptorChecks S; // RmDirRecursive may call opendir(). 2725ffd83dbSDimitry Andric RmDirRecursive(TempPath("FuzzWithFork", ".dir")); 2730b57cec5SDimitry Andric // Stop right now, don't perform any at-exit actions. 2740b57cec5SDimitry Andric _Exit(Options.InterruptExitCode); 2750b57cec5SDimitry Andric } 2760b57cec5SDimitry Andric 2770b57cec5SDimitry Andric NO_SANITIZE_MEMORY 2780b57cec5SDimitry Andric void Fuzzer::AlarmCallback() { 2790b57cec5SDimitry Andric assert(Options.UnitTimeoutSec > 0); 28068d75effSDimitry Andric // In Windows and Fuchsia, Alarm callback is executed by a different thread. 2810b57cec5SDimitry Andric // NetBSD's current behavior needs this change too. 28268d75effSDimitry Andric #if !LIBFUZZER_WINDOWS && !LIBFUZZER_NETBSD && !LIBFUZZER_FUCHSIA 2830b57cec5SDimitry Andric if (!InFuzzingThread()) 2840b57cec5SDimitry Andric return; 2850b57cec5SDimitry Andric #endif 2860b57cec5SDimitry Andric if (!RunningUserCallback) 2870b57cec5SDimitry Andric return; // We have not started running units yet. 2880b57cec5SDimitry Andric size_t Seconds = 2890b57cec5SDimitry Andric duration_cast<seconds>(system_clock::now() - UnitStartTime).count(); 2900b57cec5SDimitry Andric if (Seconds == 0) 2910b57cec5SDimitry Andric return; 2920b57cec5SDimitry Andric if (Options.Verbosity >= 2) 2930b57cec5SDimitry Andric Printf("AlarmCallback %zd\n", Seconds); 2940b57cec5SDimitry Andric if (Seconds >= (size_t)Options.UnitTimeoutSec) { 2950b57cec5SDimitry Andric if (EF->__sanitizer_acquire_crash_state && 2960b57cec5SDimitry Andric !EF->__sanitizer_acquire_crash_state()) 2970b57cec5SDimitry Andric return; 2980b57cec5SDimitry Andric Printf("ALARM: working on the last Unit for %zd seconds\n", Seconds); 2990b57cec5SDimitry Andric Printf(" and the timeout value is %d (use -timeout=N to change)\n", 3000b57cec5SDimitry Andric Options.UnitTimeoutSec); 3010b57cec5SDimitry Andric DumpCurrentUnit("timeout-"); 30206c3fb27SDimitry Andric Printf("==%lu== ERROR: libFuzzer: timeout after %zu seconds\n", GetPid(), 3030b57cec5SDimitry Andric Seconds); 3040b57cec5SDimitry Andric PrintStackTrace(); 3050b57cec5SDimitry Andric Printf("SUMMARY: libFuzzer: timeout\n"); 3060b57cec5SDimitry Andric PrintFinalStats(); 3070b57cec5SDimitry Andric _Exit(Options.TimeoutExitCode); // Stop right now. 3080b57cec5SDimitry Andric } 3090b57cec5SDimitry Andric } 3100b57cec5SDimitry Andric 3110b57cec5SDimitry Andric void Fuzzer::RssLimitCallback() { 3120b57cec5SDimitry Andric if (EF->__sanitizer_acquire_crash_state && 3130b57cec5SDimitry Andric !EF->__sanitizer_acquire_crash_state()) 3140b57cec5SDimitry Andric return; 31506c3fb27SDimitry Andric Printf("==%lu== ERROR: libFuzzer: out-of-memory (used: %zdMb; limit: %dMb)\n", 3160b57cec5SDimitry Andric GetPid(), GetPeakRSSMb(), Options.RssLimitMb); 3170b57cec5SDimitry Andric Printf(" To change the out-of-memory limit use -rss_limit_mb=<N>\n\n"); 3180b57cec5SDimitry Andric PrintMemoryProfile(); 3190b57cec5SDimitry Andric DumpCurrentUnit("oom-"); 3200b57cec5SDimitry Andric Printf("SUMMARY: libFuzzer: out-of-memory\n"); 3210b57cec5SDimitry Andric PrintFinalStats(); 3220b57cec5SDimitry Andric _Exit(Options.OOMExitCode); // Stop right now. 3230b57cec5SDimitry Andric } 3240b57cec5SDimitry Andric 32568d75effSDimitry Andric void Fuzzer::PrintStats(const char *Where, const char *End, size_t Units, 32668d75effSDimitry Andric size_t Features) { 3270b57cec5SDimitry Andric size_t ExecPerSec = execPerSec(); 3280b57cec5SDimitry Andric if (!Options.Verbosity) 3290b57cec5SDimitry Andric return; 3300b57cec5SDimitry Andric Printf("#%zd\t%s", TotalNumberOfRuns, Where); 3310b57cec5SDimitry Andric if (size_t N = TPC.GetTotalPCCoverage()) 3320b57cec5SDimitry Andric Printf(" cov: %zd", N); 33368d75effSDimitry Andric if (size_t N = Features ? Features : Corpus.NumFeatures()) 3340b57cec5SDimitry Andric Printf(" ft: %zd", N); 3350b57cec5SDimitry Andric if (!Corpus.empty()) { 3360b57cec5SDimitry Andric Printf(" corp: %zd", Corpus.NumActiveUnits()); 3370b57cec5SDimitry Andric if (size_t N = Corpus.SizeInBytes()) { 3380b57cec5SDimitry Andric if (N < (1 << 14)) 3390b57cec5SDimitry Andric Printf("/%zdb", N); 3400b57cec5SDimitry Andric else if (N < (1 << 24)) 3410b57cec5SDimitry Andric Printf("/%zdKb", N >> 10); 3420b57cec5SDimitry Andric else 3430b57cec5SDimitry Andric Printf("/%zdMb", N >> 20); 3440b57cec5SDimitry Andric } 3450b57cec5SDimitry Andric if (size_t FF = Corpus.NumInputsThatTouchFocusFunction()) 3460b57cec5SDimitry Andric Printf(" focus: %zd", FF); 3470b57cec5SDimitry Andric } 3480b57cec5SDimitry Andric if (TmpMaxMutationLen) 3490b57cec5SDimitry Andric Printf(" lim: %zd", TmpMaxMutationLen); 3500b57cec5SDimitry Andric if (Units) 3510b57cec5SDimitry Andric Printf(" units: %zd", Units); 3520b57cec5SDimitry Andric 3530b57cec5SDimitry Andric Printf(" exec/s: %zd", ExecPerSec); 3540b57cec5SDimitry Andric Printf(" rss: %zdMb", GetPeakRSSMb()); 3550b57cec5SDimitry Andric Printf("%s", End); 3560b57cec5SDimitry Andric } 3570b57cec5SDimitry Andric 3580b57cec5SDimitry Andric void Fuzzer::PrintFinalStats() { 359e8d8bef9SDimitry Andric if (Options.PrintFullCoverage) 360e8d8bef9SDimitry Andric TPC.PrintCoverage(/*PrintAllCounters=*/true); 3610b57cec5SDimitry Andric if (Options.PrintCoverage) 362e8d8bef9SDimitry Andric TPC.PrintCoverage(/*PrintAllCounters=*/false); 3630b57cec5SDimitry Andric if (Options.PrintCorpusStats) 3640b57cec5SDimitry Andric Corpus.PrintStats(); 3650b57cec5SDimitry Andric if (!Options.PrintFinalStats) 3660b57cec5SDimitry Andric return; 3670b57cec5SDimitry Andric size_t ExecPerSec = execPerSec(); 3680b57cec5SDimitry Andric Printf("stat::number_of_executed_units: %zd\n", TotalNumberOfRuns); 3690b57cec5SDimitry Andric Printf("stat::average_exec_per_sec: %zd\n", ExecPerSec); 3700b57cec5SDimitry Andric Printf("stat::new_units_added: %zd\n", NumberOfNewUnitsAdded); 37106c3fb27SDimitry Andric Printf("stat::slowest_unit_time_sec: %ld\n", TimeOfLongestUnitInSeconds); 3720b57cec5SDimitry Andric Printf("stat::peak_rss_mb: %zd\n", GetPeakRSSMb()); 3730b57cec5SDimitry Andric } 3740b57cec5SDimitry Andric 3750b57cec5SDimitry Andric void Fuzzer::SetMaxInputLen(size_t MaxInputLen) { 3760b57cec5SDimitry Andric assert(this->MaxInputLen == 0); // Can only reset MaxInputLen from 0 to non-0. 3770b57cec5SDimitry Andric assert(MaxInputLen); 3780b57cec5SDimitry Andric this->MaxInputLen = MaxInputLen; 3790b57cec5SDimitry Andric this->MaxMutationLen = MaxInputLen; 3800b57cec5SDimitry Andric AllocateCurrentUnitData(); 3810b57cec5SDimitry Andric Printf("INFO: -max_len is not provided; " 3820b57cec5SDimitry Andric "libFuzzer will not generate inputs larger than %zd bytes\n", 3830b57cec5SDimitry Andric MaxInputLen); 3840b57cec5SDimitry Andric } 3850b57cec5SDimitry Andric 3860b57cec5SDimitry Andric void Fuzzer::SetMaxMutationLen(size_t MaxMutationLen) { 3870b57cec5SDimitry Andric assert(MaxMutationLen && MaxMutationLen <= MaxInputLen); 3880b57cec5SDimitry Andric this->MaxMutationLen = MaxMutationLen; 3890b57cec5SDimitry Andric } 3900b57cec5SDimitry Andric 3910b57cec5SDimitry Andric void Fuzzer::CheckExitOnSrcPosOrItem() { 3920b57cec5SDimitry Andric if (!Options.ExitOnSrcPos.empty()) { 393349cc55cSDimitry Andric static auto *PCsSet = new std::set<uintptr_t>; 3940b57cec5SDimitry Andric auto HandlePC = [&](const TracePC::PCTableEntry *TE) { 3950b57cec5SDimitry Andric if (!PCsSet->insert(TE->PC).second) 3960b57cec5SDimitry Andric return; 3970b57cec5SDimitry Andric std::string Descr = DescribePC("%F %L", TE->PC + 1); 3980b57cec5SDimitry Andric if (Descr.find(Options.ExitOnSrcPos) != std::string::npos) { 3990b57cec5SDimitry Andric Printf("INFO: found line matching '%s', exiting.\n", 4000b57cec5SDimitry Andric Options.ExitOnSrcPos.c_str()); 4010b57cec5SDimitry Andric _Exit(0); 4020b57cec5SDimitry Andric } 4030b57cec5SDimitry Andric }; 4040b57cec5SDimitry Andric TPC.ForEachObservedPC(HandlePC); 4050b57cec5SDimitry Andric } 4060b57cec5SDimitry Andric if (!Options.ExitOnItem.empty()) { 4070b57cec5SDimitry Andric if (Corpus.HasUnit(Options.ExitOnItem)) { 4080b57cec5SDimitry Andric Printf("INFO: found item with checksum '%s', exiting.\n", 4090b57cec5SDimitry Andric Options.ExitOnItem.c_str()); 4100b57cec5SDimitry Andric _Exit(0); 4110b57cec5SDimitry Andric } 4120b57cec5SDimitry Andric } 4130b57cec5SDimitry Andric } 4140b57cec5SDimitry Andric 4150b57cec5SDimitry Andric void Fuzzer::RereadOutputCorpus(size_t MaxSize) { 4160b57cec5SDimitry Andric if (Options.OutputCorpus.empty() || !Options.ReloadIntervalSec) 4170b57cec5SDimitry Andric return; 418349cc55cSDimitry Andric std::vector<Unit> AdditionalCorpus; 419349cc55cSDimitry Andric std::vector<std::string> AdditionalCorpusPaths; 420fe6060f1SDimitry Andric ReadDirToVectorOfUnits( 421fe6060f1SDimitry Andric Options.OutputCorpus.c_str(), &AdditionalCorpus, 4220b57cec5SDimitry Andric &EpochOfLastReadOfOutputCorpus, MaxSize, 423fe6060f1SDimitry Andric /*ExitOnError*/ false, 424fe6060f1SDimitry Andric (Options.Verbosity >= 2 ? &AdditionalCorpusPaths : nullptr)); 4250b57cec5SDimitry Andric if (Options.Verbosity >= 2) 4260b57cec5SDimitry Andric Printf("Reload: read %zd new units.\n", AdditionalCorpus.size()); 4270b57cec5SDimitry Andric bool Reloaded = false; 428fe6060f1SDimitry Andric for (size_t i = 0; i != AdditionalCorpus.size(); ++i) { 429fe6060f1SDimitry Andric auto &U = AdditionalCorpus[i]; 4300b57cec5SDimitry Andric if (U.size() > MaxSize) 4310b57cec5SDimitry Andric U.resize(MaxSize); 4320b57cec5SDimitry Andric if (!Corpus.HasUnit(U)) { 4330b57cec5SDimitry Andric if (RunOne(U.data(), U.size())) { 4340b57cec5SDimitry Andric CheckExitOnSrcPosOrItem(); 4350b57cec5SDimitry Andric Reloaded = true; 436fe6060f1SDimitry Andric if (Options.Verbosity >= 2) 437fe6060f1SDimitry Andric Printf("Reloaded %s\n", AdditionalCorpusPaths[i].c_str()); 4380b57cec5SDimitry Andric } 4390b57cec5SDimitry Andric } 4400b57cec5SDimitry Andric } 4410b57cec5SDimitry Andric if (Reloaded) 4420b57cec5SDimitry Andric PrintStats("RELOAD"); 4430b57cec5SDimitry Andric } 4440b57cec5SDimitry Andric 4450b57cec5SDimitry Andric void Fuzzer::PrintPulseAndReportSlowInput(const uint8_t *Data, size_t Size) { 4460b57cec5SDimitry Andric auto TimeOfUnit = 4470b57cec5SDimitry Andric duration_cast<seconds>(UnitStopTime - UnitStartTime).count(); 4480b57cec5SDimitry Andric if (!(TotalNumberOfRuns & (TotalNumberOfRuns - 1)) && 4490b57cec5SDimitry Andric secondsSinceProcessStartUp() >= 2) 4500b57cec5SDimitry Andric PrintStats("pulse "); 451fe6060f1SDimitry Andric auto Threshhold = 452fe6060f1SDimitry Andric static_cast<long>(static_cast<double>(TimeOfLongestUnitInSeconds) * 1.1); 453fe6060f1SDimitry Andric if (TimeOfUnit > Threshhold && TimeOfUnit >= Options.ReportSlowUnits) { 4540b57cec5SDimitry Andric TimeOfLongestUnitInSeconds = TimeOfUnit; 45506c3fb27SDimitry Andric Printf("Slowest unit: %ld s:\n", TimeOfLongestUnitInSeconds); 4560b57cec5SDimitry Andric WriteUnitToFileWithPrefix({Data, Data + Size}, "slow-unit-"); 4570b57cec5SDimitry Andric } 4580b57cec5SDimitry Andric } 4590b57cec5SDimitry Andric 4600b57cec5SDimitry Andric static void WriteFeatureSetToFile(const std::string &FeaturesDir, 4610b57cec5SDimitry Andric const std::string &FileName, 462349cc55cSDimitry Andric const std::vector<uint32_t> &FeatureSet) { 4630b57cec5SDimitry Andric if (FeaturesDir.empty() || FeatureSet.empty()) return; 4640b57cec5SDimitry Andric WriteToFile(reinterpret_cast<const uint8_t *>(FeatureSet.data()), 4650b57cec5SDimitry Andric FeatureSet.size() * sizeof(FeatureSet[0]), 4660b57cec5SDimitry Andric DirPlusFile(FeaturesDir, FileName)); 4670b57cec5SDimitry Andric } 4680b57cec5SDimitry Andric 4690b57cec5SDimitry Andric static void RenameFeatureSetFile(const std::string &FeaturesDir, 4700b57cec5SDimitry Andric const std::string &OldFile, 4710b57cec5SDimitry Andric const std::string &NewFile) { 4720b57cec5SDimitry Andric if (FeaturesDir.empty()) return; 4730b57cec5SDimitry Andric RenameFile(DirPlusFile(FeaturesDir, OldFile), 4740b57cec5SDimitry Andric DirPlusFile(FeaturesDir, NewFile)); 4750b57cec5SDimitry Andric } 4760b57cec5SDimitry Andric 477e8d8bef9SDimitry Andric static void WriteEdgeToMutationGraphFile(const std::string &MutationGraphFile, 478e8d8bef9SDimitry Andric const InputInfo *II, 479e8d8bef9SDimitry Andric const InputInfo *BaseII, 480e8d8bef9SDimitry Andric const std::string &MS) { 481e8d8bef9SDimitry Andric if (MutationGraphFile.empty()) 482e8d8bef9SDimitry Andric return; 483e8d8bef9SDimitry Andric 484e8d8bef9SDimitry Andric std::string Sha1 = Sha1ToString(II->Sha1); 485e8d8bef9SDimitry Andric 486e8d8bef9SDimitry Andric std::string OutputString; 487e8d8bef9SDimitry Andric 488e8d8bef9SDimitry Andric // Add a new vertex. 489e8d8bef9SDimitry Andric OutputString.append("\""); 490e8d8bef9SDimitry Andric OutputString.append(Sha1); 491e8d8bef9SDimitry Andric OutputString.append("\"\n"); 492e8d8bef9SDimitry Andric 493e8d8bef9SDimitry Andric // Add a new edge if there is base input. 494e8d8bef9SDimitry Andric if (BaseII) { 495e8d8bef9SDimitry Andric std::string BaseSha1 = Sha1ToString(BaseII->Sha1); 496e8d8bef9SDimitry Andric OutputString.append("\""); 497e8d8bef9SDimitry Andric OutputString.append(BaseSha1); 498e8d8bef9SDimitry Andric OutputString.append("\" -> \""); 499e8d8bef9SDimitry Andric OutputString.append(Sha1); 500e8d8bef9SDimitry Andric OutputString.append("\" [label=\""); 501e8d8bef9SDimitry Andric OutputString.append(MS); 502e8d8bef9SDimitry Andric OutputString.append("\"];\n"); 503e8d8bef9SDimitry Andric } 504e8d8bef9SDimitry Andric 505e8d8bef9SDimitry Andric AppendToFile(OutputString, MutationGraphFile); 506e8d8bef9SDimitry Andric } 507e8d8bef9SDimitry Andric 5080b57cec5SDimitry Andric bool Fuzzer::RunOne(const uint8_t *Data, size_t Size, bool MayDeleteFile, 509e8d8bef9SDimitry Andric InputInfo *II, bool ForceAddToCorpus, 510e8d8bef9SDimitry Andric bool *FoundUniqFeatures) { 5110b57cec5SDimitry Andric if (!Size) 5120b57cec5SDimitry Andric return false; 513fe6060f1SDimitry Andric // Largest input length should be INT_MAX. 514fe6060f1SDimitry Andric assert(Size < std::numeric_limits<uint32_t>::max()); 5150b57cec5SDimitry Andric 51681ad6265SDimitry Andric if(!ExecuteCallback(Data, Size)) return false; 517e8d8bef9SDimitry Andric auto TimeOfUnit = duration_cast<microseconds>(UnitStopTime - UnitStartTime); 5180b57cec5SDimitry Andric 5190b57cec5SDimitry Andric UniqFeatureSetTmp.clear(); 5200b57cec5SDimitry Andric size_t FoundUniqFeaturesOfII = 0; 5210b57cec5SDimitry Andric size_t NumUpdatesBefore = Corpus.NumFeatureUpdates(); 522fe6060f1SDimitry Andric TPC.CollectFeatures([&](uint32_t Feature) { 523fe6060f1SDimitry Andric if (Corpus.AddFeature(Feature, static_cast<uint32_t>(Size), Options.Shrink)) 5240b57cec5SDimitry Andric UniqFeatureSetTmp.push_back(Feature); 5255ffd83dbSDimitry Andric if (Options.Entropic) 5265ffd83dbSDimitry Andric Corpus.UpdateFeatureFrequency(II, Feature); 527e8d8bef9SDimitry Andric if (Options.ReduceInputs && II && !II->NeverReduce) 5280b57cec5SDimitry Andric if (std::binary_search(II->UniqFeatureSet.begin(), 5290b57cec5SDimitry Andric II->UniqFeatureSet.end(), Feature)) 5300b57cec5SDimitry Andric FoundUniqFeaturesOfII++; 5310b57cec5SDimitry Andric }); 5320b57cec5SDimitry Andric if (FoundUniqFeatures) 5330b57cec5SDimitry Andric *FoundUniqFeatures = FoundUniqFeaturesOfII; 5340b57cec5SDimitry Andric PrintPulseAndReportSlowInput(Data, Size); 5350b57cec5SDimitry Andric size_t NumNewFeatures = Corpus.NumFeatureUpdates() - NumUpdatesBefore; 536e8d8bef9SDimitry Andric if (NumNewFeatures || ForceAddToCorpus) { 5370b57cec5SDimitry Andric TPC.UpdateObservedPCs(); 538e8d8bef9SDimitry Andric auto NewII = 539e8d8bef9SDimitry Andric Corpus.AddToCorpus({Data, Data + Size}, NumNewFeatures, MayDeleteFile, 540e8d8bef9SDimitry Andric TPC.ObservedFocusFunction(), ForceAddToCorpus, 541e8d8bef9SDimitry Andric TimeOfUnit, UniqFeatureSetTmp, DFT, II); 5420b57cec5SDimitry Andric WriteFeatureSetToFile(Options.FeaturesDir, Sha1ToString(NewII->Sha1), 5430b57cec5SDimitry Andric NewII->UniqFeatureSet); 544e8d8bef9SDimitry Andric WriteEdgeToMutationGraphFile(Options.MutationGraphFile, NewII, II, 545e8d8bef9SDimitry Andric MD.MutationSequence()); 5460b57cec5SDimitry Andric return true; 5470b57cec5SDimitry Andric } 5480b57cec5SDimitry Andric if (II && FoundUniqFeaturesOfII && 5490b57cec5SDimitry Andric II->DataFlowTraceForFocusFunction.empty() && 5500b57cec5SDimitry Andric FoundUniqFeaturesOfII == II->UniqFeatureSet.size() && 5510b57cec5SDimitry Andric II->U.size() > Size) { 5520b57cec5SDimitry Andric auto OldFeaturesFile = Sha1ToString(II->Sha1); 553349cc55cSDimitry Andric Corpus.Replace(II, {Data, Data + Size}, TimeOfUnit); 5540b57cec5SDimitry Andric RenameFeatureSetFile(Options.FeaturesDir, OldFeaturesFile, 5550b57cec5SDimitry Andric Sha1ToString(II->Sha1)); 5560b57cec5SDimitry Andric return true; 5570b57cec5SDimitry Andric } 5580b57cec5SDimitry Andric return false; 5590b57cec5SDimitry Andric } 5600b57cec5SDimitry Andric 561e8d8bef9SDimitry Andric void Fuzzer::TPCUpdateObservedPCs() { TPC.UpdateObservedPCs(); } 562e8d8bef9SDimitry Andric 5630b57cec5SDimitry Andric size_t Fuzzer::GetCurrentUnitInFuzzingThead(const uint8_t **Data) const { 5640b57cec5SDimitry Andric assert(InFuzzingThread()); 5650b57cec5SDimitry Andric *Data = CurrentUnitData; 5660b57cec5SDimitry Andric return CurrentUnitSize; 5670b57cec5SDimitry Andric } 5680b57cec5SDimitry Andric 5690b57cec5SDimitry Andric void Fuzzer::CrashOnOverwrittenData() { 57068d75effSDimitry Andric Printf("==%d== ERROR: libFuzzer: fuzz target overwrites its const input\n", 5710b57cec5SDimitry Andric GetPid()); 57268d75effSDimitry Andric PrintStackTrace(); 57368d75effSDimitry Andric Printf("SUMMARY: libFuzzer: overwrites-const-input\n"); 5740b57cec5SDimitry Andric DumpCurrentUnit("crash-"); 57568d75effSDimitry Andric PrintFinalStats(); 5760b57cec5SDimitry Andric _Exit(Options.ErrorExitCode); // Stop right now. 5770b57cec5SDimitry Andric } 5780b57cec5SDimitry Andric 5790b57cec5SDimitry Andric // Compare two arrays, but not all bytes if the arrays are large. 5800b57cec5SDimitry Andric static bool LooseMemeq(const uint8_t *A, const uint8_t *B, size_t Size) { 5810b57cec5SDimitry Andric const size_t Limit = 64; 5820b57cec5SDimitry Andric if (Size <= 64) 5830b57cec5SDimitry Andric return !memcmp(A, B, Size); 5840b57cec5SDimitry Andric // Compare first and last Limit/2 bytes. 5850b57cec5SDimitry Andric return !memcmp(A, B, Limit / 2) && 5860b57cec5SDimitry Andric !memcmp(A + Size - Limit / 2, B + Size - Limit / 2, Limit / 2); 5870b57cec5SDimitry Andric } 5880b57cec5SDimitry Andric 589fe6060f1SDimitry Andric // This method is not inlined because it would cause a test to fail where it 590fe6060f1SDimitry Andric // is part of the stack unwinding. See D97975 for details. 59181ad6265SDimitry Andric ATTRIBUTE_NOINLINE bool Fuzzer::ExecuteCallback(const uint8_t *Data, 592fe6060f1SDimitry Andric size_t Size) { 5930b57cec5SDimitry Andric TPC.RecordInitialStack(); 5940b57cec5SDimitry Andric TotalNumberOfRuns++; 5950b57cec5SDimitry Andric assert(InFuzzingThread()); 5960b57cec5SDimitry Andric // We copy the contents of Unit into a separate heap buffer 5970b57cec5SDimitry Andric // so that we reliably find buffer overflows in it. 5980b57cec5SDimitry Andric uint8_t *DataCopy = new uint8_t[Size]; 5990b57cec5SDimitry Andric memcpy(DataCopy, Data, Size); 6000b57cec5SDimitry Andric if (EF->__msan_unpoison) 6010b57cec5SDimitry Andric EF->__msan_unpoison(DataCopy, Size); 6020b57cec5SDimitry Andric if (EF->__msan_unpoison_param) 6030b57cec5SDimitry Andric EF->__msan_unpoison_param(2); 6040b57cec5SDimitry Andric if (CurrentUnitData && CurrentUnitData != Data) 6050b57cec5SDimitry Andric memcpy(CurrentUnitData, Data, Size); 6060b57cec5SDimitry Andric CurrentUnitSize = Size; 60781ad6265SDimitry Andric int CBRes = 0; 6080b57cec5SDimitry Andric { 6090b57cec5SDimitry Andric ScopedEnableMsanInterceptorChecks S; 6100b57cec5SDimitry Andric AllocTracer.Start(Options.TraceMalloc); 6110b57cec5SDimitry Andric UnitStartTime = system_clock::now(); 6120b57cec5SDimitry Andric TPC.ResetMaps(); 6130b57cec5SDimitry Andric RunningUserCallback = true; 61481ad6265SDimitry Andric CBRes = CB(DataCopy, Size); 6150b57cec5SDimitry Andric RunningUserCallback = false; 6160b57cec5SDimitry Andric UnitStopTime = system_clock::now(); 61781ad6265SDimitry Andric assert(CBRes == 0 || CBRes == -1); 6180b57cec5SDimitry Andric HasMoreMallocsThanFrees = AllocTracer.Stop(); 6190b57cec5SDimitry Andric } 6200b57cec5SDimitry Andric if (!LooseMemeq(DataCopy, Data, Size)) 6210b57cec5SDimitry Andric CrashOnOverwrittenData(); 6220b57cec5SDimitry Andric CurrentUnitSize = 0; 6230b57cec5SDimitry Andric delete[] DataCopy; 62481ad6265SDimitry Andric return CBRes == 0; 6250b57cec5SDimitry Andric } 6260b57cec5SDimitry Andric 6270b57cec5SDimitry Andric std::string Fuzzer::WriteToOutputCorpus(const Unit &U) { 6280b57cec5SDimitry Andric if (Options.OnlyASCII) 6290b57cec5SDimitry Andric assert(IsASCII(U)); 6300b57cec5SDimitry Andric if (Options.OutputCorpus.empty()) 6310b57cec5SDimitry Andric return ""; 6320b57cec5SDimitry Andric std::string Path = DirPlusFile(Options.OutputCorpus, Hash(U)); 6330b57cec5SDimitry Andric WriteToFile(U, Path); 6340b57cec5SDimitry Andric if (Options.Verbosity >= 2) 6350b57cec5SDimitry Andric Printf("Written %zd bytes to %s\n", U.size(), Path.c_str()); 6360b57cec5SDimitry Andric return Path; 6370b57cec5SDimitry Andric } 6380b57cec5SDimitry Andric 6390b57cec5SDimitry Andric void Fuzzer::WriteUnitToFileWithPrefix(const Unit &U, const char *Prefix) { 6400b57cec5SDimitry Andric if (!Options.SaveArtifacts) 6410b57cec5SDimitry Andric return; 6420b57cec5SDimitry Andric std::string Path = Options.ArtifactPrefix + Prefix + Hash(U); 6430b57cec5SDimitry Andric if (!Options.ExactArtifactPath.empty()) 6440b57cec5SDimitry Andric Path = Options.ExactArtifactPath; // Overrides ArtifactPrefix. 6450b57cec5SDimitry Andric WriteToFile(U, Path); 6460b57cec5SDimitry Andric Printf("artifact_prefix='%s'; Test unit written to %s\n", 6470b57cec5SDimitry Andric Options.ArtifactPrefix.c_str(), Path.c_str()); 6480b57cec5SDimitry Andric if (U.size() <= kMaxUnitSizeToPrint) 6490b57cec5SDimitry Andric Printf("Base64: %s\n", Base64(U).c_str()); 6500b57cec5SDimitry Andric } 6510b57cec5SDimitry Andric 6520b57cec5SDimitry Andric void Fuzzer::PrintStatusForNewUnit(const Unit &U, const char *Text) { 6530b57cec5SDimitry Andric if (!Options.PrintNEW) 6540b57cec5SDimitry Andric return; 6550b57cec5SDimitry Andric PrintStats(Text, ""); 6560b57cec5SDimitry Andric if (Options.Verbosity) { 6570b57cec5SDimitry Andric Printf(" L: %zd/%zd ", U.size(), Corpus.MaxInputSize()); 658e8d8bef9SDimitry Andric MD.PrintMutationSequence(Options.Verbosity >= 2); 6590b57cec5SDimitry Andric Printf("\n"); 6600b57cec5SDimitry Andric } 6610b57cec5SDimitry Andric } 6620b57cec5SDimitry Andric 6630b57cec5SDimitry Andric void Fuzzer::ReportNewCoverage(InputInfo *II, const Unit &U) { 6640b57cec5SDimitry Andric II->NumSuccessfullMutations++; 6650b57cec5SDimitry Andric MD.RecordSuccessfulMutationSequence(); 6660b57cec5SDimitry Andric PrintStatusForNewUnit(U, II->Reduced ? "REDUCE" : "NEW "); 6670b57cec5SDimitry Andric WriteToOutputCorpus(U); 6680b57cec5SDimitry Andric NumberOfNewUnitsAdded++; 6690b57cec5SDimitry Andric CheckExitOnSrcPosOrItem(); // Check only after the unit is saved to corpus. 6700b57cec5SDimitry Andric LastCorpusUpdateRun = TotalNumberOfRuns; 6710b57cec5SDimitry Andric } 6720b57cec5SDimitry Andric 6730b57cec5SDimitry Andric // Tries detecting a memory leak on the particular input that we have just 6740b57cec5SDimitry Andric // executed before calling this function. 6750b57cec5SDimitry Andric void Fuzzer::TryDetectingAMemoryLeak(const uint8_t *Data, size_t Size, 6760b57cec5SDimitry Andric bool DuringInitialCorpusExecution) { 6770b57cec5SDimitry Andric if (!HasMoreMallocsThanFrees) 6780b57cec5SDimitry Andric return; // mallocs==frees, a leak is unlikely. 6790b57cec5SDimitry Andric if (!Options.DetectLeaks) 6800b57cec5SDimitry Andric return; 6810b57cec5SDimitry Andric if (!DuringInitialCorpusExecution && 6820b57cec5SDimitry Andric TotalNumberOfRuns >= Options.MaxNumberOfRuns) 6830b57cec5SDimitry Andric return; 6840b57cec5SDimitry Andric if (!&(EF->__lsan_enable) || !&(EF->__lsan_disable) || 6850b57cec5SDimitry Andric !(EF->__lsan_do_recoverable_leak_check)) 6860b57cec5SDimitry Andric return; // No lsan. 6870b57cec5SDimitry Andric // Run the target once again, but with lsan disabled so that if there is 6880b57cec5SDimitry Andric // a real leak we do not report it twice. 6890b57cec5SDimitry Andric EF->__lsan_disable(); 6900b57cec5SDimitry Andric ExecuteCallback(Data, Size); 6910b57cec5SDimitry Andric EF->__lsan_enable(); 6920b57cec5SDimitry Andric if (!HasMoreMallocsThanFrees) 6930b57cec5SDimitry Andric return; // a leak is unlikely. 6940b57cec5SDimitry Andric if (NumberOfLeakDetectionAttempts++ > 1000) { 6950b57cec5SDimitry Andric Options.DetectLeaks = false; 6960b57cec5SDimitry Andric Printf("INFO: libFuzzer disabled leak detection after every mutation.\n" 6970b57cec5SDimitry Andric " Most likely the target function accumulates allocated\n" 6980b57cec5SDimitry Andric " memory in a global state w/o actually leaking it.\n" 6990b57cec5SDimitry Andric " You may try running this binary with -trace_malloc=[12]" 7000b57cec5SDimitry Andric " to get a trace of mallocs and frees.\n" 7010b57cec5SDimitry Andric " If LeakSanitizer is enabled in this process it will still\n" 7020b57cec5SDimitry Andric " run on the process shutdown.\n"); 7030b57cec5SDimitry Andric return; 7040b57cec5SDimitry Andric } 7050b57cec5SDimitry Andric // Now perform the actual lsan pass. This is expensive and we must ensure 7060b57cec5SDimitry Andric // we don't call it too often. 7070b57cec5SDimitry Andric if (EF->__lsan_do_recoverable_leak_check()) { // Leak is found, report it. 7080b57cec5SDimitry Andric if (DuringInitialCorpusExecution) 7090b57cec5SDimitry Andric Printf("\nINFO: a leak has been found in the initial corpus.\n\n"); 7100b57cec5SDimitry Andric Printf("INFO: to ignore leaks on libFuzzer side use -detect_leaks=0.\n\n"); 7110b57cec5SDimitry Andric CurrentUnitSize = Size; 7120b57cec5SDimitry Andric DumpCurrentUnit("leak-"); 7130b57cec5SDimitry Andric PrintFinalStats(); 7140b57cec5SDimitry Andric _Exit(Options.ErrorExitCode); // not exit() to disable lsan further on. 7150b57cec5SDimitry Andric } 7160b57cec5SDimitry Andric } 7170b57cec5SDimitry Andric 7180b57cec5SDimitry Andric void Fuzzer::MutateAndTestOne() { 7190b57cec5SDimitry Andric MD.StartMutationSequence(); 7200b57cec5SDimitry Andric 7210b57cec5SDimitry Andric auto &II = Corpus.ChooseUnitToMutate(MD.GetRand()); 722e8d8bef9SDimitry Andric if (Options.DoCrossOver) { 723e8d8bef9SDimitry Andric auto &CrossOverII = Corpus.ChooseUnitToCrossOverWith( 724e8d8bef9SDimitry Andric MD.GetRand(), Options.CrossOverUniformDist); 725e8d8bef9SDimitry Andric MD.SetCrossOverWith(&CrossOverII.U); 726e8d8bef9SDimitry Andric } 7270b57cec5SDimitry Andric const auto &U = II.U; 7280b57cec5SDimitry Andric memcpy(BaseSha1, II.Sha1, sizeof(BaseSha1)); 7290b57cec5SDimitry Andric assert(CurrentUnitData); 7300b57cec5SDimitry Andric size_t Size = U.size(); 7310b57cec5SDimitry Andric assert(Size <= MaxInputLen && "Oversized Unit"); 7320b57cec5SDimitry Andric memcpy(CurrentUnitData, U.data(), Size); 7330b57cec5SDimitry Andric 7340b57cec5SDimitry Andric assert(MaxMutationLen > 0); 7350b57cec5SDimitry Andric 7360b57cec5SDimitry Andric size_t CurrentMaxMutationLen = 7370b57cec5SDimitry Andric Min(MaxMutationLen, Max(U.size(), TmpMaxMutationLen)); 7380b57cec5SDimitry Andric assert(CurrentMaxMutationLen > 0); 7390b57cec5SDimitry Andric 7400b57cec5SDimitry Andric for (int i = 0; i < Options.MutateDepth; i++) { 7410b57cec5SDimitry Andric if (TotalNumberOfRuns >= Options.MaxNumberOfRuns) 7420b57cec5SDimitry Andric break; 7430b57cec5SDimitry Andric MaybeExitGracefully(); 7440b57cec5SDimitry Andric size_t NewSize = 0; 7450b57cec5SDimitry Andric if (II.HasFocusFunction && !II.DataFlowTraceForFocusFunction.empty() && 7460b57cec5SDimitry Andric Size <= CurrentMaxMutationLen) 7470b57cec5SDimitry Andric NewSize = MD.MutateWithMask(CurrentUnitData, Size, Size, 7480b57cec5SDimitry Andric II.DataFlowTraceForFocusFunction); 7490b57cec5SDimitry Andric 7500b57cec5SDimitry Andric // If MutateWithMask either failed or wasn't called, call default Mutate. 7510b57cec5SDimitry Andric if (!NewSize) 7520b57cec5SDimitry Andric NewSize = MD.Mutate(CurrentUnitData, Size, CurrentMaxMutationLen); 7530b57cec5SDimitry Andric assert(NewSize > 0 && "Mutator returned empty unit"); 7540b57cec5SDimitry Andric assert(NewSize <= CurrentMaxMutationLen && "Mutator return oversized unit"); 7550b57cec5SDimitry Andric Size = NewSize; 7560b57cec5SDimitry Andric II.NumExecutedMutations++; 7575ffd83dbSDimitry Andric Corpus.IncrementNumExecutedMutations(); 7580b57cec5SDimitry Andric 7590b57cec5SDimitry Andric bool FoundUniqFeatures = false; 7600b57cec5SDimitry Andric bool NewCov = RunOne(CurrentUnitData, Size, /*MayDeleteFile=*/true, &II, 761e8d8bef9SDimitry Andric /*ForceAddToCorpus*/ false, &FoundUniqFeatures); 7620b57cec5SDimitry Andric TryDetectingAMemoryLeak(CurrentUnitData, Size, 7630b57cec5SDimitry Andric /*DuringInitialCorpusExecution*/ false); 7640b57cec5SDimitry Andric if (NewCov) { 7650b57cec5SDimitry Andric ReportNewCoverage(&II, {CurrentUnitData, CurrentUnitData + Size}); 7660b57cec5SDimitry Andric break; // We will mutate this input more in the next rounds. 7670b57cec5SDimitry Andric } 7680b57cec5SDimitry Andric if (Options.ReduceDepth && !FoundUniqFeatures) 7690b57cec5SDimitry Andric break; 7700b57cec5SDimitry Andric } 7715ffd83dbSDimitry Andric 7725ffd83dbSDimitry Andric II.NeedsEnergyUpdate = true; 7730b57cec5SDimitry Andric } 7740b57cec5SDimitry Andric 7750b57cec5SDimitry Andric void Fuzzer::PurgeAllocator() { 7760b57cec5SDimitry Andric if (Options.PurgeAllocatorIntervalSec < 0 || !EF->__sanitizer_purge_allocator) 7770b57cec5SDimitry Andric return; 7780b57cec5SDimitry Andric if (duration_cast<seconds>(system_clock::now() - 7790b57cec5SDimitry Andric LastAllocatorPurgeAttemptTime) 7800b57cec5SDimitry Andric .count() < Options.PurgeAllocatorIntervalSec) 7810b57cec5SDimitry Andric return; 7820b57cec5SDimitry Andric 7830b57cec5SDimitry Andric if (Options.RssLimitMb <= 0 || 7840b57cec5SDimitry Andric GetPeakRSSMb() > static_cast<size_t>(Options.RssLimitMb) / 2) 7850b57cec5SDimitry Andric EF->__sanitizer_purge_allocator(); 7860b57cec5SDimitry Andric 7870b57cec5SDimitry Andric LastAllocatorPurgeAttemptTime = system_clock::now(); 7880b57cec5SDimitry Andric } 7890b57cec5SDimitry Andric 790349cc55cSDimitry Andric void Fuzzer::ReadAndExecuteSeedCorpora(std::vector<SizedFile> &CorporaFiles) { 7910b57cec5SDimitry Andric const size_t kMaxSaneLen = 1 << 20; 7920b57cec5SDimitry Andric const size_t kMinDefaultLen = 4096; 7930b57cec5SDimitry Andric size_t MaxSize = 0; 7940b57cec5SDimitry Andric size_t MinSize = -1; 7950b57cec5SDimitry Andric size_t TotalSize = 0; 7960b57cec5SDimitry Andric for (auto &File : CorporaFiles) { 7970b57cec5SDimitry Andric MaxSize = Max(File.Size, MaxSize); 7980b57cec5SDimitry Andric MinSize = Min(File.Size, MinSize); 7990b57cec5SDimitry Andric TotalSize += File.Size; 8000b57cec5SDimitry Andric } 8010b57cec5SDimitry Andric if (Options.MaxLen == 0) 802*5f757f3fSDimitry Andric SetMaxInputLen(std::clamp(MaxSize, kMinDefaultLen, kMaxSaneLen)); 8030b57cec5SDimitry Andric assert(MaxInputLen > 0); 8040b57cec5SDimitry Andric 8050b57cec5SDimitry Andric // Test the callback with empty input and never try it again. 8060b57cec5SDimitry Andric uint8_t dummy = 0; 8070b57cec5SDimitry Andric ExecuteCallback(&dummy, 0); 8080b57cec5SDimitry Andric 8090b57cec5SDimitry Andric if (CorporaFiles.empty()) { 8100b57cec5SDimitry Andric Printf("INFO: A corpus is not provided, starting from an empty corpus\n"); 8110b57cec5SDimitry Andric Unit U({'\n'}); // Valid ASCII input. 8120b57cec5SDimitry Andric RunOne(U.data(), U.size()); 8130b57cec5SDimitry Andric } else { 8140b57cec5SDimitry Andric Printf("INFO: seed corpus: files: %zd min: %zdb max: %zdb total: %zdb" 8150b57cec5SDimitry Andric " rss: %zdMb\n", 8160b57cec5SDimitry Andric CorporaFiles.size(), MinSize, MaxSize, TotalSize, GetPeakRSSMb()); 8170b57cec5SDimitry Andric if (Options.ShuffleAtStartUp) 8180b57cec5SDimitry Andric std::shuffle(CorporaFiles.begin(), CorporaFiles.end(), MD.GetRand()); 8190b57cec5SDimitry Andric 8200b57cec5SDimitry Andric if (Options.PreferSmall) { 8210b57cec5SDimitry Andric std::stable_sort(CorporaFiles.begin(), CorporaFiles.end()); 8220b57cec5SDimitry Andric assert(CorporaFiles.front().Size <= CorporaFiles.back().Size); 8230b57cec5SDimitry Andric } 8240b57cec5SDimitry Andric 8250b57cec5SDimitry Andric // Load and execute inputs one by one. 8260b57cec5SDimitry Andric for (auto &SF : CorporaFiles) { 8270b57cec5SDimitry Andric auto U = FileToVector(SF.File, MaxInputLen, /*ExitOnError=*/false); 8280b57cec5SDimitry Andric assert(U.size() <= MaxInputLen); 829e8d8bef9SDimitry Andric RunOne(U.data(), U.size(), /*MayDeleteFile*/ false, /*II*/ nullptr, 830e8d8bef9SDimitry Andric /*ForceAddToCorpus*/ Options.KeepSeed, 831e8d8bef9SDimitry Andric /*FoundUniqFeatures*/ nullptr); 8320b57cec5SDimitry Andric CheckExitOnSrcPosOrItem(); 8330b57cec5SDimitry Andric TryDetectingAMemoryLeak(U.data(), U.size(), 8340b57cec5SDimitry Andric /*DuringInitialCorpusExecution*/ true); 8350b57cec5SDimitry Andric } 8360b57cec5SDimitry Andric } 8370b57cec5SDimitry Andric 8380b57cec5SDimitry Andric PrintStats("INITED"); 8395ffd83dbSDimitry Andric if (!Options.FocusFunction.empty()) { 8400b57cec5SDimitry Andric Printf("INFO: %zd/%zd inputs touch the focus function\n", 8410b57cec5SDimitry Andric Corpus.NumInputsThatTouchFocusFunction(), Corpus.size()); 8420b57cec5SDimitry Andric if (!Options.DataFlowTrace.empty()) 8430b57cec5SDimitry Andric Printf("INFO: %zd/%zd inputs have the Data Flow Trace\n", 8445ffd83dbSDimitry Andric Corpus.NumInputsWithDataFlowTrace(), 8455ffd83dbSDimitry Andric Corpus.NumInputsThatTouchFocusFunction()); 8465ffd83dbSDimitry Andric } 8470b57cec5SDimitry Andric 8480b57cec5SDimitry Andric if (Corpus.empty() && Options.MaxNumberOfRuns) { 84981ad6265SDimitry Andric Printf("WARNING: no interesting inputs were found so far. " 85081ad6265SDimitry Andric "Is the code instrumented for coverage?\n" 85181ad6265SDimitry Andric "This may also happen if the target rejected all inputs we tried so " 85281ad6265SDimitry Andric "far\n"); 85381ad6265SDimitry Andric // The remaining logic requires that the corpus is not empty, 85481ad6265SDimitry Andric // so we add one fake input to the in-memory corpus. 85581ad6265SDimitry Andric Corpus.AddToCorpus({'\n'}, /*NumFeatures=*/1, /*MayDeleteFile=*/true, 85681ad6265SDimitry Andric /*HasFocusFunction=*/false, /*NeverReduce=*/false, 85781ad6265SDimitry Andric /*TimeOfUnit=*/duration_cast<microseconds>(0s), {0}, DFT, 85881ad6265SDimitry Andric /*BaseII*/ nullptr); 8590b57cec5SDimitry Andric } 8600b57cec5SDimitry Andric } 8610b57cec5SDimitry Andric 862349cc55cSDimitry Andric void Fuzzer::Loop(std::vector<SizedFile> &CorporaFiles) { 8630b57cec5SDimitry Andric auto FocusFunctionOrAuto = Options.FocusFunction; 8640b57cec5SDimitry Andric DFT.Init(Options.DataFlowTrace, &FocusFunctionOrAuto, CorporaFiles, 8650b57cec5SDimitry Andric MD.GetRand()); 8660b57cec5SDimitry Andric TPC.SetFocusFunction(FocusFunctionOrAuto); 8670b57cec5SDimitry Andric ReadAndExecuteSeedCorpora(CorporaFiles); 8680b57cec5SDimitry Andric DFT.Clear(); // No need for DFT any more. 8690b57cec5SDimitry Andric TPC.SetPrintNewPCs(Options.PrintNewCovPcs); 8700b57cec5SDimitry Andric TPC.SetPrintNewFuncs(Options.PrintNewCovFuncs); 8710b57cec5SDimitry Andric system_clock::time_point LastCorpusReload = system_clock::now(); 8720b57cec5SDimitry Andric 8730b57cec5SDimitry Andric TmpMaxMutationLen = 8740b57cec5SDimitry Andric Min(MaxMutationLen, Max(size_t(4), Corpus.MaxInputSize())); 8750b57cec5SDimitry Andric 8760b57cec5SDimitry Andric while (true) { 8770b57cec5SDimitry Andric auto Now = system_clock::now(); 8780b57cec5SDimitry Andric if (!Options.StopFile.empty() && 8790b57cec5SDimitry Andric !FileToVector(Options.StopFile, 1, false).empty()) 8800b57cec5SDimitry Andric break; 8810b57cec5SDimitry Andric if (duration_cast<seconds>(Now - LastCorpusReload).count() >= 8820b57cec5SDimitry Andric Options.ReloadIntervalSec) { 8830b57cec5SDimitry Andric RereadOutputCorpus(MaxInputLen); 8840b57cec5SDimitry Andric LastCorpusReload = system_clock::now(); 8850b57cec5SDimitry Andric } 8860b57cec5SDimitry Andric if (TotalNumberOfRuns >= Options.MaxNumberOfRuns) 8870b57cec5SDimitry Andric break; 8880b57cec5SDimitry Andric if (TimedOut()) 8890b57cec5SDimitry Andric break; 8900b57cec5SDimitry Andric 8910b57cec5SDimitry Andric // Update TmpMaxMutationLen 8920b57cec5SDimitry Andric if (Options.LenControl) { 8930b57cec5SDimitry Andric if (TmpMaxMutationLen < MaxMutationLen && 8940b57cec5SDimitry Andric TotalNumberOfRuns - LastCorpusUpdateRun > 8950b57cec5SDimitry Andric Options.LenControl * Log(TmpMaxMutationLen)) { 8960b57cec5SDimitry Andric TmpMaxMutationLen = 8970b57cec5SDimitry Andric Min(MaxMutationLen, TmpMaxMutationLen + Log(TmpMaxMutationLen)); 8980b57cec5SDimitry Andric LastCorpusUpdateRun = TotalNumberOfRuns; 8990b57cec5SDimitry Andric } 9000b57cec5SDimitry Andric } else { 9010b57cec5SDimitry Andric TmpMaxMutationLen = MaxMutationLen; 9020b57cec5SDimitry Andric } 9030b57cec5SDimitry Andric 9040b57cec5SDimitry Andric // Perform several mutations and runs. 9050b57cec5SDimitry Andric MutateAndTestOne(); 9060b57cec5SDimitry Andric 9070b57cec5SDimitry Andric PurgeAllocator(); 9080b57cec5SDimitry Andric } 9090b57cec5SDimitry Andric 9100b57cec5SDimitry Andric PrintStats("DONE ", "\n"); 9110b57cec5SDimitry Andric MD.PrintRecommendedDictionary(); 9120b57cec5SDimitry Andric } 9130b57cec5SDimitry Andric 9140b57cec5SDimitry Andric void Fuzzer::MinimizeCrashLoop(const Unit &U) { 9150b57cec5SDimitry Andric if (U.size() <= 1) 9160b57cec5SDimitry Andric return; 9170b57cec5SDimitry Andric while (!TimedOut() && TotalNumberOfRuns < Options.MaxNumberOfRuns) { 9180b57cec5SDimitry Andric MD.StartMutationSequence(); 9190b57cec5SDimitry Andric memcpy(CurrentUnitData, U.data(), U.size()); 9200b57cec5SDimitry Andric for (int i = 0; i < Options.MutateDepth; i++) { 9210b57cec5SDimitry Andric size_t NewSize = MD.Mutate(CurrentUnitData, U.size(), MaxMutationLen); 9220b57cec5SDimitry Andric assert(NewSize > 0 && NewSize <= MaxMutationLen); 9230b57cec5SDimitry Andric ExecuteCallback(CurrentUnitData, NewSize); 9240b57cec5SDimitry Andric PrintPulseAndReportSlowInput(CurrentUnitData, NewSize); 9250b57cec5SDimitry Andric TryDetectingAMemoryLeak(CurrentUnitData, NewSize, 9260b57cec5SDimitry Andric /*DuringInitialCorpusExecution*/ false); 9270b57cec5SDimitry Andric } 9280b57cec5SDimitry Andric } 9290b57cec5SDimitry Andric } 9300b57cec5SDimitry Andric 9310b57cec5SDimitry Andric } // namespace fuzzer 9320b57cec5SDimitry Andric 9330b57cec5SDimitry Andric extern "C" { 9340b57cec5SDimitry Andric 9350b57cec5SDimitry Andric ATTRIBUTE_INTERFACE size_t 9360b57cec5SDimitry Andric LLVMFuzzerMutate(uint8_t *Data, size_t Size, size_t MaxSize) { 9370b57cec5SDimitry Andric assert(fuzzer::F); 9380b57cec5SDimitry Andric return fuzzer::F->GetMD().DefaultMutate(Data, Size, MaxSize); 9390b57cec5SDimitry Andric } 9400b57cec5SDimitry Andric 9410b57cec5SDimitry Andric } // extern "C" 942