summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/fuzzer/FuzzerDriver.cpp1
-rw-r--r--lib/fuzzer/FuzzerExtFunctions.def1
-rw-r--r--lib/fuzzer/FuzzerFlags.def4
-rw-r--r--lib/fuzzer/FuzzerInternal.h3
-rw-r--r--lib/fuzzer/FuzzerLoop.cpp23
-rw-r--r--lib/fuzzer/FuzzerOptions.h1
6 files changed, 32 insertions, 1 deletions
diff --git a/lib/fuzzer/FuzzerDriver.cpp b/lib/fuzzer/FuzzerDriver.cpp
index 29248dcee..18c73ca75 100644
--- a/lib/fuzzer/FuzzerDriver.cpp
+++ b/lib/fuzzer/FuzzerDriver.cpp
@@ -578,6 +578,7 @@ int FuzzerDriver(int *argc, char ***argv, UserCallback Callback) {
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)
diff --git a/lib/fuzzer/FuzzerExtFunctions.def b/lib/fuzzer/FuzzerExtFunctions.def
index 3bc5302c3..25a655bfd 100644
--- a/lib/fuzzer/FuzzerExtFunctions.def
+++ b/lib/fuzzer/FuzzerExtFunctions.def
@@ -33,6 +33,7 @@ EXT_FUNC(__sanitizer_install_malloc_and_free_hooks, int,
(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,
diff --git a/lib/fuzzer/FuzzerFlags.def b/lib/fuzzer/FuzzerFlags.def
index efbc06790..e4bca46f0 100644
--- a/lib/fuzzer/FuzzerFlags.def
+++ b/lib/fuzzer/FuzzerFlags.def
@@ -114,6 +114,10 @@ FUZZER_FLAG_INT(close_fd_mask, 0, "If 1, close stdout at startup; "
"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 <N> 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"
diff --git a/lib/fuzzer/FuzzerInternal.h b/lib/fuzzer/FuzzerInternal.h
index 34fdeb821..97c14085e 100644
--- a/lib/fuzzer/FuzzerInternal.h
+++ b/lib/fuzzer/FuzzerInternal.h
@@ -96,6 +96,7 @@ private:
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 @@ private:
bool HasMoreMallocsThanFrees = false;
size_t NumberOfLeakDetectionAttempts = 0;
+ system_clock::time_point LastAllocatorPurgeAttemptTime = system_clock::now();
+
UserCallback CB;
InputCorpus &Corpus;
MutationDispatcher &MD;
diff --git a/lib/fuzzer/FuzzerLoop.cpp b/lib/fuzzer/FuzzerLoop.cpp
index 30844e328..58e8168d1 100644
--- a/lib/fuzzer/FuzzerLoop.cpp
+++ b/lib/fuzzer/FuzzerLoop.cpp
@@ -587,7 +587,7 @@ void Fuzzer::MutateAndTestOne() {
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::MutateAndTestOne() {
}
}
+void Fuzzer::PurgeAllocator() {
+ if (Options.PurgeAllocatorIntervalSec < 0 ||
+ !EF->__sanitizer_purge_allocator) {
+ return;
+ }
+ if (duration_cast<seconds>(system_clock::now() -
+ LastAllocatorPurgeAttemptTime).count() <
+ Options.PurgeAllocatorIntervalSec) {
+ return;
+ }
+
+ if (Options.RssLimitMb <= 0 ||
+ GetPeakRSSMb() > static_cast<size_t>(Options.RssLimitMb) / 2) {
+ EF->__sanitizer_purge_allocator();
+ }
+
+ LastAllocatorPurgeAttemptTime = system_clock::now();
+}
+
void Fuzzer::ReadAndExecuteSeedCorpora(const Vector<std::string> &CorpusDirs) {
const size_t kMaxSaneLen = 1 << 20;
const size_t kMinDefaultLen = 4096;
@@ -699,6 +718,8 @@ void Fuzzer::Loop(const Vector<std::string> &CorpusDirs) {
// Perform several mutations and runs.
MutateAndTestOne();
+
+ PurgeAllocator();
}
PrintStats("DONE ", "\n");
diff --git a/lib/fuzzer/FuzzerOptions.h b/lib/fuzzer/FuzzerOptions.h
index e57c7df5b..73953e154 100644
--- a/lib/fuzzer/FuzzerOptions.h
+++ b/lib/fuzzer/FuzzerOptions.h
@@ -54,6 +54,7 @@ struct FuzzingOptions {
bool DumpCoverage = false;
bool UseClangCoverage = false;
bool DetectLeaks = true;
+ int PurgeAllocatorIntervalSec = 1;
int UseFeatureFrequency = false;
int TraceMalloc = 0;
bool HandleAbrt = false;