Index: lib/Fuzzer/CMakeLists.txt =================================================================== --- lib/Fuzzer/CMakeLists.txt +++ lib/Fuzzer/CMakeLists.txt @@ -24,6 +24,8 @@ FuzzerUtil.cpp FuzzerUtilDarwin.cpp FuzzerUtilLinux.cpp + FuzzerUtilPosix.cpp + FuzzerUtilWindows.cpp ) add_library(LLVMFuzzerNoMain STATIC $ Index: lib/Fuzzer/FuzzerDriver.cpp =================================================================== --- lib/Fuzzer/FuzzerDriver.cpp +++ 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: lib/Fuzzer/FuzzerUtil.h =================================================================== --- lib/Fuzzer/FuzzerUtil.h +++ 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 *memmem(const void *haystack, size_t haystacklen, + const void *needle, size_t needlelen); + } // namespace fuzzer #endif // LLVM_FUZZER_UTIL_H Index: lib/Fuzzer/FuzzerUtil.cpp =================================================================== --- lib/Fuzzer/FuzzerUtil.cpp +++ lib/Fuzzer/FuzzerUtil.cpp @@ -12,20 +12,14 @@ #include "FuzzerUtil.h" #include "FuzzerInternal.h" #include "FuzzerIO.h" -#include -#include -#include -#include -#include -#include #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,13 +195,34 @@ 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"); - if (!Pipe) return false; + FILE *Pipe = OpenProcessPipe(Command.c_str(), "r"); + if (!Pipe) { + Printf("OpenProcessPipe failed with %d.\n", errno); + exit(1); + } + char Buff[1024]; size_t N; - while ((N = fread(Buff, 1, sizeof(Buff), Pipe)) > 0) + while ((N = fread(Buff, 1, sizeof(Buff), Pipe)) == sizeof(Buff)) Out->append(Buff, N); + if (ferror(Pipe)) { + Printf("Failed to read opened process pipe.\n"); + exit(1); + } + // Add last data read. + Out->append(Buff, N); + return true; } Index: lib/Fuzzer/FuzzerUtilPosix.cpp =================================================================== --- /dev/null +++ lib/Fuzzer/FuzzerUtilPosix.cpp @@ -0,0 +1,99 @@ +//===- 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 "FuzzerInternal.h" +#include "FuzzerIO.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); +} + +} // namespace fuzzer +#endif // LIBFUZZER_POSIX Index: lib/Fuzzer/FuzzerUtilWindows.cpp =================================================================== --- /dev/null +++ lib/Fuzzer/FuzzerUtilWindows.cpp @@ -0,0 +1,199 @@ +//===- 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 "FuzzerInternal.h" +#include "FuzzerIO.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); +} + +const void *memmem(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; +} + +int ExecuteCommand(const std::string &Command) { + return system(Command.c_str()); +} + +} // namespace fuzzer +#endif // LIBFUZZER_WINDOWS