Index: compiler-rt/trunk/lib/fuzzer/FuzzerDriver.cpp =================================================================== --- compiler-rt/trunk/lib/fuzzer/FuzzerDriver.cpp +++ compiler-rt/trunk/lib/fuzzer/FuzzerDriver.cpp @@ -578,6 +578,7 @@ Options.ReloadIntervalSec = Flags.reload; Options.OnlyASCII = Flags.only_ascii; Options.DetectLeaks = Flags.detect_leaks; + Options.PurgeAllocatorIntervalSec = Flags.purge_allocator_interval; Options.TraceMalloc = Flags.trace_malloc; Options.RssLimitMb = Flags.rss_limit_mb; if (Flags.runs >= 0) Index: compiler-rt/trunk/lib/fuzzer/FuzzerExtFunctions.def =================================================================== --- compiler-rt/trunk/lib/fuzzer/FuzzerExtFunctions.def +++ compiler-rt/trunk/lib/fuzzer/FuzzerExtFunctions.def @@ -33,6 +33,7 @@ (void (*malloc_hook)(const volatile void *, size_t), void (*free_hook)(const volatile void *)), false); +EXT_FUNC(__sanitizer_purge_allocator, void, (), false); EXT_FUNC(__sanitizer_print_memory_profile, int, (size_t, size_t), false); EXT_FUNC(__sanitizer_print_stack_trace, void, (), true); EXT_FUNC(__sanitizer_symbolize_pc, void, Index: compiler-rt/trunk/lib/fuzzer/FuzzerFlags.def =================================================================== --- compiler-rt/trunk/lib/fuzzer/FuzzerFlags.def +++ compiler-rt/trunk/lib/fuzzer/FuzzerFlags.def @@ -114,6 +114,10 @@ "Be careful, this will also close e.g. asan's stderr/stdout.") FUZZER_FLAG_INT(detect_leaks, 1, "If 1, and if LeakSanitizer is enabled " "try to detect memory leaks during fuzzing (i.e. not only at shut down).") +FUZZER_FLAG_INT(purge_allocator_interval, 1, "Purge allocator caches and " + "quarantines every seconds. When rss_limit_mb is specified (>0), " + "purging starts when RSS exceeds 50% of rss_limit_mb. Pass " + "purge_allocator_interval=-1 to disable this functionality.") FUZZER_FLAG_INT(trace_malloc, 0, "If >= 1 will print all mallocs/frees. " "If >= 2 will also print stack traces.") FUZZER_FLAG_INT(rss_limit_mb, 2048, "If non-zero, the fuzzer will exit upon" Index: compiler-rt/trunk/lib/fuzzer/FuzzerInternal.h =================================================================== --- compiler-rt/trunk/lib/fuzzer/FuzzerInternal.h +++ compiler-rt/trunk/lib/fuzzer/FuzzerInternal.h @@ -96,6 +96,7 @@ void CrashOnOverwrittenData(); void InterruptCallback(); void MutateAndTestOne(); + void PurgeAllocator(); void ReportNewCoverage(InputInfo *II, const Unit &U); void PrintPulseAndReportSlowInput(const uint8_t *Data, size_t Size); void WriteToOutputCorpus(const Unit &U); @@ -124,6 +125,8 @@ bool HasMoreMallocsThanFrees = false; size_t NumberOfLeakDetectionAttempts = 0; + system_clock::time_point LastAllocatorPurgeAttemptTime = system_clock::now(); + UserCallback CB; InputCorpus &Corpus; MutationDispatcher &MD; Index: compiler-rt/trunk/lib/fuzzer/FuzzerLoop.cpp =================================================================== --- compiler-rt/trunk/lib/fuzzer/FuzzerLoop.cpp +++ compiler-rt/trunk/lib/fuzzer/FuzzerLoop.cpp @@ -587,7 +587,7 @@ size_t NewSize = 0; NewSize = MD.Mutate(CurrentUnitData, Size, CurrentMaxMutationLen); assert(NewSize > 0 && "Mutator returned empty unit"); - assert(NewSize <= CurrentMaxMutationLen && "Mutator return overisized unit"); + assert(NewSize <= CurrentMaxMutationLen && "Mutator return oversized unit"); Size = NewSize; II.NumExecutedMutations++; if (RunOne(CurrentUnitData, Size, /*MayDeleteFile=*/true, &II)) @@ -598,6 +598,25 @@ } } +void Fuzzer::PurgeAllocator() { + if (Options.PurgeAllocatorIntervalSec < 0 || + !EF->__sanitizer_purge_allocator) { + return; + } + if (duration_cast(system_clock::now() - + LastAllocatorPurgeAttemptTime).count() < + Options.PurgeAllocatorIntervalSec) { + return; + } + + if (Options.RssLimitMb <= 0 || + GetPeakRSSMb() > static_cast(Options.RssLimitMb) / 2) { + EF->__sanitizer_purge_allocator(); + } + + LastAllocatorPurgeAttemptTime = system_clock::now(); +} + void Fuzzer::ReadAndExecuteSeedCorpora(const Vector &CorpusDirs) { const size_t kMaxSaneLen = 1 << 20; const size_t kMinDefaultLen = 4096; @@ -699,6 +718,8 @@ // Perform several mutations and runs. MutateAndTestOne(); + + PurgeAllocator(); } PrintStats("DONE ", "\n"); Index: compiler-rt/trunk/lib/fuzzer/FuzzerOptions.h =================================================================== --- compiler-rt/trunk/lib/fuzzer/FuzzerOptions.h +++ compiler-rt/trunk/lib/fuzzer/FuzzerOptions.h @@ -54,6 +54,7 @@ bool DumpCoverage = false; bool UseClangCoverage = false; bool DetectLeaks = true; + int PurgeAllocatorIntervalSec = 1; int UseFeatureFrequency = false; int TraceMalloc = 0; bool HandleAbrt = false;