Index: llvm/trunk/lib/Fuzzer/CMakeLists.txt =================================================================== --- llvm/trunk/lib/Fuzzer/CMakeLists.txt +++ llvm/trunk/lib/Fuzzer/CMakeLists.txt @@ -24,6 +24,8 @@ FuzzerUtil.cpp FuzzerUtilDarwin.cpp FuzzerUtilLinux.cpp + FuzzerUtilPosix.cpp + FuzzerUtilWindows.cpp ) add_library(LLVMFuzzerNoMain STATIC $ Index: llvm/trunk/lib/Fuzzer/FuzzerDriver.cpp =================================================================== --- llvm/trunk/lib/Fuzzer/FuzzerDriver.cpp +++ llvm/trunk/lib/Fuzzer/FuzzerDriver.cpp @@ -23,7 +23,6 @@ #include #include #include -#include // This function should be present in the libFuzzer so that the client // binary can test for its existence. @@ -442,7 +441,7 @@ // Initialize Seed. if (Seed == 0) Seed = (std::chrono::system_clock::now().time_since_epoch().count() << 10) + - getpid(); + GetPid(); if (Flags.verbosity) Printf("INFO: Seed: %u\n", Seed); Index: llvm/trunk/lib/Fuzzer/FuzzerMutate.cpp =================================================================== --- llvm/trunk/lib/Fuzzer/FuzzerMutate.cpp +++ llvm/trunk/lib/Fuzzer/FuzzerMutate.cpp @@ -221,7 +221,7 @@ size_t NumPositions = 0; for (const uint8_t *Cur = Data; Cur < End && NumPositions < kMaxNumPositions; Cur++) { - Cur = (uint8_t *)memmem(Cur, End - Cur, &ExistingBytes, sizeof(T)); + Cur = (uint8_t *)SearchMemory(Cur, End - Cur, &ExistingBytes, sizeof(T)); if (!Cur) break; Positions[NumPositions++] = Cur - Data; } Index: llvm/trunk/lib/Fuzzer/FuzzerTraceState.cpp =================================================================== --- llvm/trunk/lib/Fuzzer/FuzzerTraceState.cpp +++ llvm/trunk/lib/Fuzzer/FuzzerTraceState.cpp @@ -157,7 +157,7 @@ const uint8_t *Beg = UnitData; const uint8_t *End = Beg + UnitSize; for (const uint8_t *Cur = Beg; Cur < End; Cur++) { - Cur = (uint8_t *)memmem(Cur, End - Cur, &PresentData, DataSize); + Cur = (uint8_t *)SearchMemory(Cur, End - Cur, &PresentData, DataSize); if (!Cur) break; size_t Pos = Cur - Beg; @@ -181,7 +181,7 @@ const uint8_t *Beg = UnitData; const uint8_t *End = Beg + UnitSize; for (const uint8_t *Cur = Beg; Cur < End; Cur++) { - Cur = (uint8_t *)memmem(Cur, End - Cur, PresentData, DataSize); + Cur = (uint8_t *)SearchMemory(Cur, End - Cur, PresentData, DataSize); if (!Cur) break; size_t Pos = Cur - Beg; Index: llvm/trunk/lib/Fuzzer/FuzzerUtil.h =================================================================== --- llvm/trunk/lib/Fuzzer/FuzzerUtil.h +++ llvm/trunk/lib/Fuzzer/FuzzerUtil.h @@ -40,6 +40,8 @@ int NumberOfCpuCores(); +bool ExecuteCommandAndReadOutput(const std::string &Command, std::string *Out); + // Platform specific functions. void SetTimer(int Seconds); @@ -57,9 +59,12 @@ size_t GetPeakRSSMb(); -bool ExecuteCommandAndReadOutput(const std::string &Command, std::string *Out); - int ExecuteCommand(const std::string &Command); +FILE *OpenProcessPipe(const char *Command, const char *Mode); + +const void *SearchMemory(const void *haystack, size_t haystacklen, + const void *needle, size_t needlelen); + } // namespace fuzzer #endif // LLVM_FUZZER_UTIL_H Index: llvm/trunk/lib/Fuzzer/FuzzerUtil.cpp =================================================================== --- llvm/trunk/lib/Fuzzer/FuzzerUtil.cpp +++ llvm/trunk/lib/Fuzzer/FuzzerUtil.cpp @@ -10,22 +10,16 @@ //===----------------------------------------------------------------------===// #include "FuzzerUtil.h" -#include "FuzzerInternal.h" #include "FuzzerIO.h" -#include -#include -#include -#include -#include -#include +#include "FuzzerInternal.h" #include #include #include -#include +#include #include #include -#include -#include +#include +#include #include namespace fuzzer { @@ -62,80 +56,6 @@ PrintASCII(U.data(), U.size(), PrintAfter); } -static void AlarmHandler(int, siginfo_t *, void *) { - Fuzzer::StaticAlarmCallback(); -} - -static void CrashHandler(int, siginfo_t *, void *) { - Fuzzer::StaticCrashSignalCallback(); -} - -static void InterruptHandler(int, siginfo_t *, void *) { - Fuzzer::StaticInterruptCallback(); -} - -static void SetSigaction(int signum, - void (*callback)(int, siginfo_t *, void *)) { - struct sigaction sigact; - memset(&sigact, 0, sizeof(sigact)); - sigact.sa_sigaction = callback; - if (sigaction(signum, &sigact, 0)) { - Printf("libFuzzer: sigaction failed with %d\n", errno); - exit(1); - } -} - -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); } -void SetSigIllHandler() { SetSigaction(SIGILL, CrashHandler); } -void SetSigFpeHandler() { SetSigaction(SIGFPE, CrashHandler); } -void SetSigIntHandler() { SetSigaction(SIGINT, InterruptHandler); } -void SetSigTermHandler() { SetSigaction(SIGTERM, InterruptHandler); } - -int NumberOfCpuCores() { - const char *CmdLine = nullptr; - if (LIBFUZZER_LINUX) { - CmdLine = "nproc"; - } else if (LIBFUZZER_APPLE) { - CmdLine = "sysctl -n hw.ncpu"; - } else { - assert(0 && "NumberOfCpuCores() is not implemented for your platform"); - } - - FILE *F = popen(CmdLine, "r"); - int N = 1; - if (!F || fscanf(F, "%d", &N) != 1) { - Printf("WARNING: Failed to parse output of command \"%s\" in %s(). " - "Assuming CPU count of 1.\n", - CmdLine, __func__); - N = 1; - } - - if (pclose(F)) { - Printf("WARNING: Executing command \"%s\" failed in %s(). " - "Assuming CPU count of 1.\n", - CmdLine, __func__); - N = 1; - } - if (N < 1) { - Printf("WARNING: Reported CPU count (%d) from command \"%s\" was invalid " - "in %s(). Assuming CPU count of 1.\n", - N, CmdLine, __func__); - N = 1; - } - return N; -} - bool ToASCII(uint8_t *Data, size_t Size) { bool Changed = false; for (size_t i = 0; i < Size; i++) { @@ -231,12 +151,6 @@ return true; } -void SleepSeconds(int Seconds) { - sleep(Seconds); // Use C API to avoid coverage from instrumented libc++. -} - -int GetPid() { return getpid(); } - std::string Base64(const Unit &U) { static const char Table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz" @@ -265,21 +179,6 @@ return Res; } -size_t GetPeakRSSMb() { - struct rusage usage; - if (getrusage(RUSAGE_SELF, &usage)) - return 0; - if (LIBFUZZER_LINUX) { - // ru_maxrss is in KiB - return usage.ru_maxrss >> 10; - } else if (LIBFUZZER_APPLE) { - // ru_maxrss is in bytes - return usage.ru_maxrss >> 20; - } - assert(0 && "GetPeakRSSMb() is not implemented for your platform"); - return 0; -} - std::string DescribePC(const char *SymbolizedFMT, uintptr_t PC) { if (!EF->__sanitizer_symbolize_pc) return ""; char PcDescr[1024]; @@ -296,8 +195,18 @@ Printf(FallbackFMT, PC); } +int NumberOfCpuCores() { + unsigned N = std::thread::hardware_concurrency(); + if (!N) { + Printf("WARNING: std::thread::hardware_concurrency not well defined for " + "your platform. Assuming CPU count of 1.\n"); + N = 1; + } + return N; +} + bool ExecuteCommandAndReadOutput(const std::string &Command, std::string *Out) { - FILE *Pipe = popen(Command.c_str(), "r"); + FILE *Pipe = OpenProcessPipe(Command.c_str(), "r"); if (!Pipe) return false; char Buff[1024]; size_t N; Index: llvm/trunk/lib/Fuzzer/FuzzerUtilPosix.cpp =================================================================== --- llvm/trunk/lib/Fuzzer/FuzzerUtilPosix.cpp +++ llvm/trunk/lib/Fuzzer/FuzzerUtilPosix.cpp @@ -0,0 +1,106 @@ +//===- FuzzerUtilPosix.cpp - Misc utils for Posix. ------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Misc utils implementation using Posix API. +//===----------------------------------------------------------------------===// + +#include "FuzzerDefs.h" +#if LIBFUZZER_POSIX +#include "FuzzerIO.h" +#include "FuzzerInternal.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace fuzzer { + +static void AlarmHandler(int, siginfo_t *, void *) { + Fuzzer::StaticAlarmCallback(); +} + +static void CrashHandler(int, siginfo_t *, void *) { + Fuzzer::StaticCrashSignalCallback(); +} + +static void InterruptHandler(int, siginfo_t *, void *) { + Fuzzer::StaticInterruptCallback(); +} + +static void SetSigaction(int signum, + void (*callback)(int, siginfo_t *, void *)) { + struct sigaction sigact; + memset(&sigact, 0, sizeof(sigact)); + sigact.sa_sigaction = callback; + if (sigaction(signum, &sigact, 0)) { + Printf("libFuzzer: sigaction failed with %d\n", errno); + exit(1); + } +} + +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); } +void SetSigIllHandler() { SetSigaction(SIGILL, CrashHandler); } +void SetSigFpeHandler() { SetSigaction(SIGFPE, CrashHandler); } +void SetSigIntHandler() { SetSigaction(SIGINT, InterruptHandler); } +void SetSigTermHandler() { SetSigaction(SIGTERM, InterruptHandler); } + +void SleepSeconds(int Seconds) { + sleep(Seconds); // Use C API to avoid coverage from instrumented libc++. +} + +int GetPid() { return getpid(); } + +size_t GetPeakRSSMb() { + struct rusage usage; + if (getrusage(RUSAGE_SELF, &usage)) + return 0; + if (LIBFUZZER_LINUX) { + // ru_maxrss is in KiB + return usage.ru_maxrss >> 10; + } else if (LIBFUZZER_APPLE) { + // ru_maxrss is in bytes + return usage.ru_maxrss >> 20; + } + assert(0 && "GetPeakRSSMb() is not implemented for your platform"); + return 0; +} + +FILE *OpenProcessPipe(const char *Command, const char *Mode) { + return popen(Command, Mode); +} + +const void *SearchMemory(const void *Data, size_t DataLen, const void *Patt, + size_t PattLen) { + return memmem(Data, DataLen, Patt, PattLen); +} + +} // namespace fuzzer +#endif // LIBFUZZER_POSIX Index: llvm/trunk/lib/Fuzzer/FuzzerUtilWindows.cpp =================================================================== --- llvm/trunk/lib/Fuzzer/FuzzerUtilWindows.cpp +++ llvm/trunk/lib/Fuzzer/FuzzerUtilWindows.cpp @@ -0,0 +1,194 @@ +//===- FuzzerUtilWindows.cpp - Misc utils for Windows. --------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Misc utils implementation for Windows. +//===----------------------------------------------------------------------===// + +#include "FuzzerDefs.h" +#if LIBFUZZER_WINDOWS +#include "FuzzerIO.h" +#include "FuzzerInternal.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace fuzzer { + +LONG WINAPI SEGVHandler(PEXCEPTION_POINTERS ExceptionInfo) { + switch (ExceptionInfo->ExceptionRecord->ExceptionCode) { + case EXCEPTION_ACCESS_VIOLATION: + case EXCEPTION_ARRAY_BOUNDS_EXCEEDED: + case EXCEPTION_STACK_OVERFLOW: + Fuzzer::StaticCrashSignalCallback(); + break; + } + return EXCEPTION_CONTINUE_SEARCH; +} + +LONG WINAPI BUSHandler(PEXCEPTION_POINTERS ExceptionInfo) { + switch (ExceptionInfo->ExceptionRecord->ExceptionCode) { + case EXCEPTION_DATATYPE_MISALIGNMENT: + case EXCEPTION_IN_PAGE_ERROR: + Fuzzer::StaticCrashSignalCallback(); + break; + } + return EXCEPTION_CONTINUE_SEARCH; +} + +LONG WINAPI ILLHandler(PEXCEPTION_POINTERS ExceptionInfo) { + switch (ExceptionInfo->ExceptionRecord->ExceptionCode) { + case EXCEPTION_ILLEGAL_INSTRUCTION: + case EXCEPTION_PRIV_INSTRUCTION: + Fuzzer::StaticCrashSignalCallback(); + break; + } + return EXCEPTION_CONTINUE_SEARCH; +} + +LONG WINAPI FPEHandler(PEXCEPTION_POINTERS ExceptionInfo) { + switch (ExceptionInfo->ExceptionRecord->ExceptionCode) { + case EXCEPTION_FLT_DENORMAL_OPERAND: + case EXCEPTION_FLT_DIVIDE_BY_ZERO: + case EXCEPTION_FLT_INEXACT_RESULT: + case EXCEPTION_FLT_INVALID_OPERATION: + case EXCEPTION_FLT_OVERFLOW: + case EXCEPTION_FLT_STACK_CHECK: + case EXCEPTION_FLT_UNDERFLOW: + case EXCEPTION_INT_DIVIDE_BY_ZERO: + case EXCEPTION_INT_OVERFLOW: + Fuzzer::StaticCrashSignalCallback(); + break; + } + return EXCEPTION_CONTINUE_SEARCH; +} + +BOOL WINAPI INTHandler(DWORD dwCtrlType) { + switch (dwCtrlType) { + case CTRL_C_EVENT: + Fuzzer::StaticInterruptCallback(); + return TRUE; + default: + return FALSE; + } +} + +BOOL WINAPI TERMHandler(DWORD dwCtrlType) { + switch (dwCtrlType) { + case CTRL_BREAK_EVENT: + Fuzzer::StaticInterruptCallback(); + return TRUE; + default: + return FALSE; + } +} + +void SetTimer(int Seconds) { + // TODO: Complete this implementation. + return; +} + +void SetSigSegvHandler() { + if (!AddVectoredExceptionHandler(1, SEGVHandler)) { + Printf("libFuzzer: AddVectoredExceptionHandler failed.\n"); + exit(1); + } +} + +void SetSigBusHandler() { + if (!AddVectoredExceptionHandler(1, BUSHandler)) { + Printf("libFuzzer: AddVectoredExceptionHandler failed.\n"); + exit(1); + } +} + +static void CrashHandler(int) { Fuzzer::StaticCrashSignalCallback(); } + +void SetSigAbrtHandler() { signal(SIGABRT, CrashHandler); } + +void SetSigIllHandler() { + if (!AddVectoredExceptionHandler(1, ILLHandler)) { + Printf("libFuzzer: AddVectoredExceptionHandler failed.\n"); + exit(1); + } +} + +void SetSigFpeHandler() { + if (!AddVectoredExceptionHandler(1, FPEHandler)) { + Printf("libFuzzer: AddVectoredExceptionHandler failed.\n"); + exit(1); + } +} + +void SetSigIntHandler() { + if (!SetConsoleCtrlHandler(INTHandler, TRUE)) { + DWORD LastError = GetLastError(); + Printf("libFuzzer: SetConsoleCtrlHandler failed (Error code: %lu).\n", + LastError); + exit(1); + } +} + +void SetSigTermHandler() { + if (!SetConsoleCtrlHandler(TERMHandler, TRUE)) { + DWORD LastError = GetLastError(); + Printf("libFuzzer: SetConsoleCtrlHandler failed (Error code: %lu).\n", + LastError); + exit(1); + } +} + +void SleepSeconds(int Seconds) { Sleep(Seconds * 1000); } + +int GetPid() { return GetCurrentProcessId(); } + +size_t GetPeakRSSMb() { + PROCESS_MEMORY_COUNTERS info; + if (!GetProcessMemoryInfo(GetCurrentProcess(), &info, sizeof(info))) + return 0; + return info.PeakWorkingSetSize >> 20; +} + +FILE *OpenProcessPipe(const char *Command, const char *Mode) { + return _popen(Command, Mode); +} + +int ExecuteCommand(const std::string &Command) { + return system(Command.c_str()); +} + +const void *SearchMemory(const void *Data, size_t DataLen, const void *Patt, + size_t PattLen) { + // TODO: make this implementation more efficient. + const char *Cdata = (const char *)Data; + const char *Cpatt = (const char *)Patt; + + if (!Data || !Patt || DataLen == 0 || PattLen == 0 || DataLen < PattLen) + return NULL; + + if (PattLen == 1) + return memchr(Data, *Cpatt, DataLen); + + const char *End = Cdata + DataLen - PattLen; + + for (const char *It = Cdata; It < End; ++It) + if (It[0] == Cpatt[0] && memcmp(It, Cpatt, PattLen) == 0) + return It; + + return NULL; +} + +} // namespace fuzzer +#endif // LIBFUZZER_WINDOWS