Options.HandleSegv = Flags.handle_segv;
Options.HandleTerm = Flags.handle_term;
Options.HandleXfsz = Flags.handle_xfsz;
+ Options.HandleUsr1 = Flags.handle_usr1;
+ Options.HandleUsr2 = Flags.handle_usr2;
SetSignalHandler(Options);
std::atexit(Fuzzer::StaticExitCallback);
FUZZER_FLAG_INT(handle_int, 1, "If 1, try to intercept SIGINT.")
FUZZER_FLAG_INT(handle_term, 1, "If 1, try to intercept SIGTERM.")
FUZZER_FLAG_INT(handle_xfsz, 1, "If 1, try to intercept SIGXFSZ.")
+FUZZER_FLAG_INT(handle_usr1, 1, "If 1, try to intercept SIGUSR1.")
+FUZZER_FLAG_INT(handle_usr2, 1, "If 1, try to intercept SIGUSR2.")
FUZZER_FLAG_INT(close_fd_mask, 0, "If 1, close stdout at startup; "
"if 2, close stderr; if 3, close both. "
"Be careful, this will also close e.g. asan's stderr/stdout.")
static void StaticExitCallback();
static void StaticInterruptCallback();
static void StaticFileSizeExceedCallback();
+ static void StaticGracefulExitCallback();
void ExecuteCallback(const uint8_t *Data, size_t Size);
bool RunOne(const uint8_t *Data, size_t Size, bool MayDeleteFile = false,
void AlarmCallback();
void CrashCallback();
void ExitCallback();
+ void MaybeExitGracefully();
void CrashOnOverwrittenData();
void InterruptCallback();
void MutateAndTestOne();
uint8_t BaseSha1[kSHA1NumBytes]; // Checksum of the base unit.
bool RunningCB = false;
+ bool GracefulExitRequested = false;
+
size_t TotalNumberOfRuns = 0;
size_t NumberOfNewUnitsAdded = 0;
F->InterruptCallback();
}
+void Fuzzer::StaticGracefulExitCallback() {
+ assert(F);
+ F->GracefulExitRequested = true;
+ Printf("INFO: signal received, trying to exit gracefully\n");
+}
+
void Fuzzer::StaticFileSizeExceedCallback() {
Printf("==%lu== ERROR: libFuzzer: file size exceeded\n", GetPid());
exit(1);
_Exit(Options.ErrorExitCode);
}
+void Fuzzer::MaybeExitGracefully() {
+ if (!GracefulExitRequested) return;
+ Printf("==%lu== INFO: libFuzzer: exiting as requested\n", GetPid());
+ PrintFinalStats();
+ _Exit(0);
+}
+
void Fuzzer::InterruptCallback() {
Printf("==%lu== libFuzzer: run interrupted; exiting\n", GetPid());
PrintFinalStats();
for (int i = 0; i < Options.MutateDepth; i++) {
if (TotalNumberOfRuns >= Options.MaxNumberOfRuns)
break;
+ MaybeExitGracefully();
size_t NewSize = 0;
NewSize = MD.Mutate(CurrentUnitData, Size, CurrentMaxMutationLen);
assert(NewSize > 0 && "Mutator returned empty unit");
std::ofstream OF(CFPath, std::ofstream::out | std::ofstream::app);
Set<size_t> AllFeatures;
for (size_t i = M.FirstNotProcessedFile; i < M.Files.size(); i++) {
+ MaybeExitGracefully();
auto U = FileToVector(M.Files[i].Name);
if (U.size() > MaxInputLen) {
U.resize(MaxInputLen);
CloneArgsWithoutX(Args, "merge"));
bool Success = false;
for (size_t Attempt = 1; Attempt <= NumAttempts; Attempt++) {
+ MaybeExitGracefully();
Printf("MERGE-OUTER: attempt %zd\n", Attempt);
auto ExitCode =
ExecuteCommand(BaseCmd.first + " -merge_control_file=" + CFPath +
bool HandleSegv = false;
bool HandleTerm = false;
bool HandleXfsz = false;
+ bool HandleUsr1 = false;
+ bool HandleUsr2 = false;
};
} // namespace fuzzer
Fuzzer::StaticInterruptCallback();
}
+static void GracefulExitHandler(int, siginfo_t *, void *) {
+ Fuzzer::StaticGracefulExitCallback();
+}
+
static void FileSizeExceedHandler(int, siginfo_t *, void *) {
Fuzzer::StaticFileSizeExceedCallback();
}
SetSigaction(SIGFPE, CrashHandler);
if (Options.HandleXfsz)
SetSigaction(SIGXFSZ, FileSizeExceedHandler);
+ if (Options.HandleUsr1)
+ SetSigaction(SIGUSR1, GracefulExitHandler);
+ if (Options.HandleUsr2)
+ SetSigaction(SIGUSR2, GracefulExitHandler);
}
void SleepSeconds(int Seconds) {
--- /dev/null
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Simple test for a fuzzer: it simply sleeps for 1 second.
+#include <cstddef>
+#include <cstdint>
+#include <thread>
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ std::this_thread::sleep_for(std::chrono::seconds(1));
+ return 0;
+}
+
--- /dev/null
+# Check that libFuzzer honors SIGUSR1/SIGUSR2
+RUN: rm -rf %t
+RUN: mkdir -p %t
+RUN: %cpp_compiler %S/SleepOneSecondTest.cpp -o %t/LFSIGUSR
+
+RUN: %t/LFSIGUSR 2> %t/log & export PID=$!
+RUN: sleep 2
+RUN: kill -SIGUSR1 $PID
+RUN: cat %t/log | FileCheck %s
+
+RUN: mkdir -p %t/C1 %t/C2
+RUN: echo a > %t/C2/a
+RUN: echo b > %t/C2/b
+RUN: echo c > %t/C2/c
+RUN: echo d > %t/C2/d
+RUN: echo e > %t/C2/e
+RUN: echo f > %t/C2/f
+RUN: echo g > %t/C2/g
+
+RUN: %t/LFSIGUSR -merge=1 -merge_control_file=%t/MCF %t/C1 %t/C2 2> %t/log & export PID=$!
+RUN: sleep 3
+RUN: killall -SIGUSR2 %t/LFSIGUSR
+RUN: cat %t/log | FileCheck %s
+RUN: grep C2/g %t/MCF
+RUN: grep STARTED %t/MCF
+RUN: grep DONE %t/MCF
+
+CHECK: INFO: signal received, trying to exit gracefully
+CHECK: INFO: libFuzzer: exiting as requested