Index: lib/Fuzzer/FuzzerInternal.h =================================================================== --- lib/Fuzzer/FuzzerInternal.h +++ lib/Fuzzer/FuzzerInternal.h @@ -17,6 +17,7 @@ #include #include #include +#include #include #include "FuzzerDefs.h" @@ -142,6 +143,8 @@ void AllocateCurrentUnitData(); uint8_t *CurrentUnitData = nullptr; std::atomic CurrentUnitSize; + bool RunningCB; + std::mutex RunningCBMtx; uint8_t BaseSha1[kSHA1NumBytes]; // Checksum of the base unit. size_t TotalNumberOfRuns = 0; Index: lib/Fuzzer/FuzzerLoop.cpp =================================================================== --- lib/Fuzzer/FuzzerLoop.cpp +++ lib/Fuzzer/FuzzerLoop.cpp @@ -157,7 +157,7 @@ Fuzzer::Fuzzer(UserCallback CB, InputCorpus &Corpus, MutationDispatcher &MD, FuzzingOptions Options) - : CB(CB), Corpus(Corpus), MD(MD), Options(Options) { + : RunningCB(false), CB(CB), Corpus(Corpus), MD(MD), Options(Options) { SetDeathCallback(); InitializeTraceState(); assert(!F); @@ -254,22 +254,25 @@ " Combine libFuzzer with AddressSanitizer or similar for better " "crash reports.\n"); Printf("SUMMARY: libFuzzer: deadly signal\n"); - DumpCurrentUnit("crash-"); - PrintFinalStats(); + if (RunningCB) { // The fuzzer is in a consistent state. + DumpCurrentUnit("crash-"); + PrintFinalStats(); + } exit(Options.ErrorExitCode); } void Fuzzer::InterruptCallback() { Printf("==%d== libFuzzer: run interrupted; exiting\n", GetPid()); - PrintFinalStats(); + if (RunningCB) // The fuzzer is in a consistent state. + PrintFinalStats(); _Exit(0); // Stop right now, don't perform any at-exit actions. } NO_SANITIZE_MEMORY void Fuzzer::AlarmCallback() { assert(Options.UnitTimeoutSec > 0); - if (!InFuzzingThread()) return; - if (!CurrentUnitSize) + std::lock_guard Lock(RunningCBMtx); + if (!RunningCB) return; // We have not started running units yet. size_t Seconds = duration_cast(system_clock::now() - UnitStartTime).count(); @@ -299,9 +302,12 @@ Printf(" To change the out-of-memory limit use -rss_limit_mb=\n\n"); if (EF->__sanitizer_print_memory_profile) EF->__sanitizer_print_memory_profile(95); - DumpCurrentUnit("oom-"); Printf("SUMMARY: libFuzzer: out-of-memory\n"); - PrintFinalStats(); + std::lock_guard Lock(RunningCBMtx); + if (RunningCB) { // The fuzzer is in a consistent state. + DumpCurrentUnit("oom-"); + PrintFinalStats(); + } _Exit(Options.ErrorExitCode); // Stop right now. } @@ -513,7 +519,13 @@ UnitStartTime = system_clock::now(); ResetCounters(); // Reset coverage right before the callback. TPC.ResetMaps(); + RunningCBMtx.lock(); + RunningCB = true; + RunningCBMtx.unlock(); int Res = CB(DataCopy, Size); + RunningCBMtx.lock(); + RunningCB = false; + RunningCBMtx.unlock(); UnitStopTime = system_clock::now(); (void)Res; assert(Res == 0); Index: lib/Fuzzer/FuzzerUtilPosix.cpp =================================================================== --- lib/Fuzzer/FuzzerUtilPosix.cpp +++ lib/Fuzzer/FuzzerUtilPosix.cpp @@ -30,10 +30,6 @@ namespace fuzzer { -static void AlarmHandler(int, siginfo_t *, void *) { - Fuzzer::StaticAlarmCallback(); -} - static void CrashHandler(int, siginfo_t *, void *) { Fuzzer::StaticCrashSignalCallback(); } @@ -53,15 +49,6 @@ } } -void SetTimer(int Seconds) { - struct itimerval T {{Seconds, 0}, {Seconds, 0}}; - if (setitimer(ITIMER_REAL, &T, nullptr)) { - Printf("libFuzzer: setitimer failed with %d\n", errno); - exit(1); - } - SetSigaction(SIGALRM, AlarmHandler); -} - void SetSigSegvHandler() { SetSigaction(SIGSEGV, CrashHandler); } void SetSigBusHandler() { SetSigaction(SIGBUS, CrashHandler); } void SetSigAbrtHandler() { SetSigaction(SIGABRT, CrashHandler); } @@ -74,6 +61,18 @@ sleep(Seconds); // Use C API to avoid coverage from instrumented libc++. } +static void TimerThread(int Seconds) { + while (true) { + SleepSeconds(Seconds); + Fuzzer::StaticAlarmCallback(); + } +} + +void SetTimer(int Seconds) { + std::thread T(TimerThread, Seconds); + T.detach(); +} + int GetPid() { return getpid(); } size_t GetPeakRSSMb() { Index: lib/Fuzzer/FuzzerUtilWindows.cpp =================================================================== --- lib/Fuzzer/FuzzerUtilWindows.cpp +++ lib/Fuzzer/FuzzerUtilWindows.cpp @@ -95,9 +95,39 @@ } } +void CALLBACK ALRMHandler(PVOID /*lpParameter*/, BOOLEAN /*TimerOrWaitFired*/) { + Fuzzer::StaticAlarmCallback(); +} + +class TimerQ { + HANDLE TimerQueue; + public: + TimerQ() : TimerQueue(NULL) {}; + ~TimerQ() { + if (TimerQueue) + DeleteTimerQueueEx(TimerQueue, NULL); + }; + void SetTimer(int Seconds) { + if (!TimerQueue) { + TimerQueue = CreateTimerQueue(); + if (!TimerQueue) { + Printf("libFuzzer: CreateTimerQueue failed.\n"); + exit(1); + } + } + HANDLE Timer; + if (!CreateTimerQueueTimer(&Timer, TimerQueue, ALRMHandler, NULL, + Seconds*1000, Seconds*1000, 0)) { + Printf("libFuzzer: CreateTimerQueueTimer failed.\n"); + exit(1); + } + }; +}; + +static TimerQ Timer; + void SetTimer(int Seconds) { - // TODO: Complete this implementation. - return; + Timer.SetTimer(Seconds); } void SetSigSegvHandler() {