[libFuzzer] teach the fork mode to ignore OOMs and timeouts

llvm-svn: 353792
This commit is contained in:
Kostya Serebryany 2019-02-12 02:18:53 +00:00
parent cfc512ab44
commit cdbb9dc962
7 changed files with 47 additions and 11 deletions

View File

@ -533,6 +533,12 @@ void FuzzWithFork(Fuzzer *F, const FuzzingOptions &Options,
Printf("INFO: temp_files: %zd files_added: %zd newft: %zd ft: %zd\n",
TempFiles.size(), FilesToAdd.size(), NewFeatures.size(),
Features.size());
// Continue if our crash is one of the ignorred ones.
if (Options.IgnoreTimeouts && ExitCode == Options.TimeoutExitCode)
continue;
if (Options.IgnoreOOMs && ExitCode == Options.OOMExitCode)
continue;
// And exit if we don't ignore this crash.
if (ExitCode != 0) break;
}
@ -681,6 +687,8 @@ int FuzzerDriver(int *argc, char ***argv, UserCallback Callback) {
Options.UnitTimeoutSec = Flags.timeout;
Options.ErrorExitCode = Flags.error_exitcode;
Options.TimeoutExitCode = Flags.timeout_exitcode;
Options.IgnoreTimeouts = Flags.ignore_timeouts;
Options.IgnoreOOMs = Flags.ignore_ooms;
Options.MaxTotalTimeSec = Flags.max_total_time;
Options.DoCrossOver = Flags.cross_over;
Options.MutateDepth = Flags.mutate_depth;

View File

@ -43,6 +43,8 @@ FUZZER_FLAG_INT(max_total_time, 0, "If positive, indicates the maximal total "
FUZZER_FLAG_INT(help, 0, "Print help.")
FUZZER_FLAG_INT(fork, 0, "Experimental mode where fuzzing happens "
"in a subprocess")
FUZZER_FLAG_INT(ignore_timeouts, 1, "Ignore timeouts in fork mode")
FUZZER_FLAG_INT(ignore_ooms, 1, "Ignore OOMs in fork mode")
FUZZER_FLAG_INT(merge, 0, "If 1, the 2-nd, 3-rd, etc corpora will be "
"merged into the 1-st corpus. Only interesting units will be taken. "
"This flag can be used to minimize a corpus.")

View File

@ -299,7 +299,6 @@ void CrashResistantMerge(const Vector<std::string> &Args,
Command BaseCmd(Args);
BaseCmd.removeFlag("merge");
BaseCmd.removeFlag("fork");
bool Success = false;
for (size_t Attempt = 1; Attempt <= NumAttempts; Attempt++) {
Fuzzer::MaybeExitGracefully();
Printf("MERGE-OUTER: attempt %zd\n", Attempt);
@ -309,14 +308,9 @@ void CrashResistantMerge(const Vector<std::string> &Args,
auto ExitCode = ExecuteCommand(Cmd);
if (!ExitCode) {
Printf("MERGE-OUTER: succesfull in %zd attempt(s)\n", Attempt);
Success = true;
break;
}
}
if (!Success) {
Printf("MERGE-OUTER: zero succesfull attempts, exiting\n");
exit(1);
}
// Read the control file and do the merge.
Merger M;
std::ifstream IF(CFPath);

View File

@ -23,6 +23,8 @@ struct FuzzingOptions {
int OOMExitCode = 71;
int InterruptExitCode = 72;
int ErrorExitCode = 77;
bool IgnoreTimeouts = 1;
bool IgnoreOOMs = 1;
int MaxTotalTimeSec = 0;
int RssLimitMb = 0;
int MallocLimitMb = 0;

View File

@ -0,0 +1,22 @@
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
// Simple test for a fuzzer.
// Here the target has a shallow OOM bug and a deeper crash.
// Make sure we can find the crash while ignoring OOMs.
#include <cstddef>
#include <cstdint>
static volatile int *Sink;
static volatile int *Zero;
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
if (Size >= 3 && Data[0] == 'O' && Data[1] == 'O' && Data[2] == 'M')
Sink = new int[1 << 28]; // instant OOM with -rss_limit_mb=128.
if (Size >= 4 && Data[0] == 'F' && Data[1] == 'U' && Data[2] == 'Z' &&
Data[3] == 'Z') // a bit deeper crash.
*Zero = 42;
return 0;
}

View File

@ -1,5 +1,16 @@
# REQUIRES: linux
CHECK: BINGO
BINGO: BINGO
RUN: %cpp_compiler %S/SimpleTest.cpp -o %t-SimpleTest
RUN: not %run %t-SimpleTest -fork=1 2>&1 | FileCheck %s --check-prefix=BINGO
RUN: not %run %t-SimpleTest -fork=1 2>&1 | FileCheck %s
TIMEOUT: ERROR: libFuzzer: timeout
RUN: %cpp_compiler %S/TimeoutTest.cpp -o %t-TimeoutTest
RUN: not %run %t-TimeoutTest -fork=1 -timeout=1 -ignore_timeouts=0 2>&1 | FileCheck %s --check-prefix=TIMEOUT
OOM: ERROR: libFuzzer: out-of-memory
RUN: %cpp_compiler %S/OutOfMemoryTest.cpp -o %t-OutOfMemoryTest
RUN: not %run %t-OutOfMemoryTest -fork=1 -ignore_ooms=0 -rss_limit_mb=128 2>&1 | FileCheck %s --check-prefix=OOM
CRASH: SEGV on unknown address 0x000000000000
RUN: %cpp_compiler %S/ShallowOOMDeepCrash.cpp -o %t-ShallowOOMDeepCrash
RUN: not %run %t-ShallowOOMDeepCrash -fork=1 -rss_limit_mb=128 2>&1 | FileCheck %s --check-prefix=CRASH

View File

@ -65,6 +65,3 @@ RUN: not grep FUZZER %t/T1/*
RUN: grep FUZZE %t/T1/*
MERGE_LEN5: MERGE-OUTER: succesfull in 1 attempt(s)
RUN: rm -rf %t/T1/* %t/T2/*
RUN: not %run %t-FullCoverageSetTest -merge=1 %t/T1 %t/T2 2>&1 | FileCheck %s --check-prefix=EMPTY
EMPTY: MERGE-OUTER: zero succesfull attempts, exiting