Index: lib/Fuzzer/CMakeLists.txt =================================================================== --- lib/Fuzzer/CMakeLists.txt +++ lib/Fuzzer/CMakeLists.txt @@ -10,18 +10,23 @@ endif() add_library(LLVMFuzzerNoMainObjects OBJECT FuzzerCrossOver.cpp - FuzzerTraceState.cpp FuzzerDriver.cpp - FuzzerExtFunctionsDlsym.cpp - FuzzerExtFunctionsWeak.cpp + FuzzerExtFunctionsApple.cpp + FuzzerExtFunctionsLinux.cpp + FuzzerExtFunctionsWindows.cpp FuzzerIO.cpp + FuzzerIOPosix.cpp + FuzzerIOWindows.cpp FuzzerLoop.cpp FuzzerMutate.cpp FuzzerSHA1.cpp FuzzerTracePC.cpp + FuzzerTraceState.cpp FuzzerUtil.cpp FuzzerUtilDarwin.cpp FuzzerUtilLinux.cpp + FuzzerUtilPosix.cpp + FuzzerUtilWindows.cpp ) add_library(LLVMFuzzerNoMain STATIC $ Index: lib/Fuzzer/FuzzerCorpus.h =================================================================== --- lib/Fuzzer/FuzzerCorpus.h +++ lib/Fuzzer/FuzzerCorpus.h @@ -14,6 +14,7 @@ #include #include +#include #include "FuzzerDefs.h" #include "FuzzerRandom.h" Index: lib/Fuzzer/FuzzerDefs.h =================================================================== --- lib/Fuzzer/FuzzerDefs.h +++ lib/Fuzzer/FuzzerDefs.h @@ -20,11 +20,15 @@ // Platform detection. #ifdef __linux__ -#define LIBFUZZER_LINUX 1 #define LIBFUZZER_APPLE 0 +#define LIBFUZZER_LINUX 1 +#define LIBFUZZER_POSIX 1 #elif __APPLE__ -#define LIBFUZZER_LINUX 0 #define LIBFUZZER_APPLE 1 +#define LIBFUZZER_LINUX 0 +#define LIBFUZZER_POSIX 1 +#elif _WIN32 +#define LIBFUZZER_WINDOWS 1 #else #error "Support for your platform has not been implemented" #endif @@ -62,6 +66,8 @@ std::string FileToString(const std::string &Path); Unit FileToVector(const std::string &Path, size_t MaxSize = 0, bool ExitOnError = true); +void ListFilesInDirRecursive(const std::string &Dir, long *Epoch, + std::vector *V, bool TopDir); void ReadDirToVectorOfUnits(const char *Path, std::vector *V, long *Epoch, size_t MaxSize, bool ExitOnError); void WriteToFile(const Unit &U, const std::string &Path); @@ -97,6 +103,11 @@ size_t GetPeakRSSMb(); +#if LIBFUZZER_WINDOWS +const void *memmem(const void *haystack, size_t haystacklen, + const void *needle, size_t needlelen); +#endif + // Private copy of SHA1 implementation. static const int kSHA1NumBytes = 20; // Computes SHA1 hash of 'Len' bytes in 'Data', writes kSHA1NumBytes to 'Out'. Index: lib/Fuzzer/FuzzerDriver.cpp =================================================================== --- lib/Fuzzer/FuzzerDriver.cpp +++ lib/Fuzzer/FuzzerDriver.cpp @@ -22,7 +22,6 @@ #include #include #include -#include // This function should be present in the libFuzzer so that the client // binary can test for its existence. @@ -441,7 +440,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/FuzzerExtFunctionsApple.cpp =================================================================== --- lib/Fuzzer/FuzzerExtFunctionsApple.cpp +++ lib/Fuzzer/FuzzerExtFunctionsApple.cpp @@ -1,4 +1,4 @@ -//===- FuzzerExtFunctionsDlsym.cpp - Interface to external functions ------===// +//===- FuzzerExtFunctionsApple.cpp - Interface to external functions ------===// // // The LLVM Compiler Infrastructure // @@ -13,7 +13,6 @@ //===----------------------------------------------------------------------===// #include "FuzzerDefs.h" #if LIBFUZZER_APPLE - #include "FuzzerExtFunctions.h" #include Index: lib/Fuzzer/FuzzerExtFunctionsLinux.cpp =================================================================== --- lib/Fuzzer/FuzzerExtFunctionsLinux.cpp +++ lib/Fuzzer/FuzzerExtFunctionsLinux.cpp @@ -1,4 +1,4 @@ -//===- FuzzerExtFunctionsWeak.cpp - Interface to external functions -------===// +//===- FuzzerExtFunctionsLinux.cpp - Interface to external functions ------===// // // The LLVM Compiler Infrastructure // @@ -14,7 +14,6 @@ //===----------------------------------------------------------------------===// #include "FuzzerDefs.h" #if LIBFUZZER_LINUX - #include "FuzzerExtFunctions.h" extern "C" { Index: lib/Fuzzer/FuzzerExtFunctionsWindows.cpp =================================================================== --- lib/Fuzzer/FuzzerExtFunctionsWindows.cpp +++ lib/Fuzzer/FuzzerExtFunctionsWindows.cpp @@ -0,0 +1,52 @@ +//===- FuzzerExtFunctionsWindows.cpp - Interface to external functions ----===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Implementation for Windows. +//===----------------------------------------------------------------------===// +#include "FuzzerDefs.h" +#if LIBFUZZER_WINDOWS +#include "FuzzerExtFunctions.h" + +using namespace fuzzer; + +extern "C" { +// Declare these symbols as weak to allow them to be optionally defined. +#define EXT_FUNC(NAME, RETURN_TYPE, FUNC_SIG, WARN) \ + RETURN_TYPE NAME ## Def FUNC_SIG { \ + Printf("ERROR: Function \"%s\" not defined.\n", #NAME); \ + exit(1); \ + } \ + RETURN_TYPE NAME FUNC_SIG __attribute__ ((weak, alias (#NAME "Def"))); + +#include "FuzzerExtFunctions.def" + +#undef EXT_FUNC +} + +template +static T* GetFnPtr(T *Fun, T *FunDef, const char *FnName, bool WarnIfMissing) { + if (Fun == FunDef) { + if (WarnIfMissing) + Printf("WARNING: Failed to find function \"%s\".\n", FnName); + return nullptr; + } + return Fun; +} + +namespace fuzzer { + +ExternalFunctions::ExternalFunctions() { +#define EXT_FUNC(NAME, RETURN_TYPE, FUNC_SIG, WARN) \ + this->NAME = GetFnPtr(::NAME, ::NAME ## Def, #NAME, WARN); + +#include "FuzzerExtFunctions.def" + +#undef EXT_FUNC +} +} // namespace fuzzer +#endif // LIBFUZZER_WINDOWS Index: lib/Fuzzer/FuzzerIO.cpp =================================================================== --- lib/Fuzzer/FuzzerIO.cpp +++ lib/Fuzzer/FuzzerIO.cpp @@ -12,24 +12,17 @@ #include "FuzzerDefs.h" #include #include -#include #include #include -#include #include #include +#include +#if LIBFUZZER_POSIX +#include +#endif namespace fuzzer { -static FILE *OutputFile = stderr; - -bool IsFile(const std::string &Path) { - struct stat St; - if (stat(Path.c_str(), &St)) - return false; - return S_ISREG(St.st_mode); -} - long GetEpoch(const std::string &Path) { struct stat St; if (stat(Path.c_str(), &St)) @@ -37,29 +30,6 @@ return St.st_mtime; } -static void ListFilesInDirRecursive(const std::string &Dir, long *Epoch, - std::vector *V, bool TopDir) { - auto E = GetEpoch(Dir); - if (Epoch) - if (E && *Epoch >= E) return; - - DIR *D = opendir(Dir.c_str()); - if (!D) { - Printf("No such directory: %s; exiting\n", Dir.c_str()); - exit(1); - } - while (auto E = readdir(D)) { - std::string Path = DirPlusFile(Dir, E->d_name); - if (E->d_type == DT_REG || E->d_type == DT_LNK) - V->push_back(Path); - else if (E->d_type == DT_DIR && *E->d_name != '.') - ListFilesInDirRecursive(Path, Epoch, V, false); - } - closedir(D); - if (Epoch && TopDir) - *Epoch = E; -} - Unit FileToVector(const std::string &Path, size_t MaxSize, bool ExitOnError) { std::ifstream T(Path); if (ExitOnError && !T) { @@ -118,32 +88,4 @@ } } -std::string DirPlusFile(const std::string &DirPath, - const std::string &FileName) { - return DirPath + "/" + FileName; -} - -void DupAndCloseStderr() { - int OutputFd = dup(2); - if (OutputFd > 0) { - FILE *NewOutputFile = fdopen(OutputFd, "w"); - if (NewOutputFile) { - OutputFile = NewOutputFile; - if (EF->__sanitizer_set_report_fd) - EF->__sanitizer_set_report_fd(reinterpret_cast(OutputFd)); - close(2); - } - } -} - -void CloseStdout() { close(1); } - -void Printf(const char *Fmt, ...) { - va_list ap; - va_start(ap, Fmt); - vfprintf(OutputFile, Fmt, ap); - va_end(ap); - fflush(OutputFile); -} - } // namespace fuzzer Index: lib/Fuzzer/FuzzerIOPosix.cpp =================================================================== --- lib/Fuzzer/FuzzerIOPosix.cpp +++ lib/Fuzzer/FuzzerIOPosix.cpp @@ -0,0 +1,89 @@ +//===- FuzzerIOPosix.cpp - IO utils for Posix. ----------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// IO functions implementation using Posix API. +//===----------------------------------------------------------------------===// + +#include "FuzzerDefs.h" +#if LIBFUZZER_POSIX +#include "FuzzerExtFunctions.h" +#include +#include +#include +#include +#include +#include +#include +#include + +namespace fuzzer { + +static FILE *OutputFile = stderr; + +bool IsFile(const std::string &Path) { + struct stat St; + if (stat(Path.c_str(), &St)) + return false; + return S_ISREG(St.st_mode); +} + +void ListFilesInDirRecursive(const std::string &Dir, long *Epoch, + std::vector *V, bool TopDir) { + auto E = GetEpoch(Dir); + if (Epoch) + if (E && *Epoch >= E) return; + + DIR *D = opendir(Dir.c_str()); + if (!D) { + Printf("No such directory: %s; exiting\n", Dir.c_str()); + exit(1); + } + while (auto E = readdir(D)) { + std::string Path = DirPlusFile(Dir, E->d_name); + if (E->d_type == DT_REG || E->d_type == DT_LNK) + V->push_back(Path); + else if (E->d_type == DT_DIR && *E->d_name != '.') + ListFilesInDirRecursive(Path, Epoch, V, false); + } + closedir(D); + if (Epoch && TopDir) + *Epoch = E; +} + +std::string DirPlusFile(const std::string &DirPath, + const std::string &FileName) { + return DirPath + "/" + FileName; +} + +void DupAndCloseStderr() { + int OutputFd = dup(2); + if (OutputFd > 0) { + FILE *NewOutputFile = fdopen(OutputFd, "w"); + if (NewOutputFile) { + OutputFile = NewOutputFile; + if (EF->__sanitizer_set_report_fd) + EF->__sanitizer_set_report_fd(reinterpret_cast(OutputFd)); + close(2); + } + } +} + +void CloseStdout() { + close(1); +} + +void Printf(const char *Fmt, ...) { + va_list ap; + va_start(ap, Fmt); + vfprintf(OutputFile, Fmt, ap); + va_end(ap); + fflush(OutputFile); +} + +} // namespace fuzzer +#endif // LIBFUZZER_POSIX Index: lib/Fuzzer/FuzzerIOWindows.cpp =================================================================== --- lib/Fuzzer/FuzzerIOWindows.cpp +++ lib/Fuzzer/FuzzerIOWindows.cpp @@ -0,0 +1,144 @@ +//===- FuzzerIOWindows.cpp - IO utils for Windows. ------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// IO functions implementation for Windows. +//===----------------------------------------------------------------------===// + +#include "FuzzerDefs.h" +#if LIBFUZZER_WINDOWS +#include "FuzzerExtFunctions.h" +#include +#include +#include +#include +#include +#include +#include +#include + +namespace fuzzer { + +static FILE *OutputFile = stderr; + +bool IsFile(const std::string &Path) { + HANDLE FileHandle( + CreateFileA(Path.c_str(), 0, FILE_SHARE_READ, NULL, OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS, 0)); + + if (GetFileType(FileHandle) != FILE_TYPE_DISK) { + CloseHandle(FileHandle); + return false; + } + + BY_HANDLE_FILE_INFORMATION Info; + if (!GetFileInformationByHandle(FileHandle, &Info) || + (Info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) { + CloseHandle(FileHandle); + return false; + } + + CloseHandle(FileHandle); + return true; +} + +void ListFilesInDirRecursive(const std::string &Dir, long *Epoch, + std::vector *V, bool TopDir) { + auto E = GetEpoch(Dir); + if (Epoch) + if (E && *Epoch >= E) return; + + std::string Path(Dir); + // Convert path to the format that Windows is happy with. + if (Path.size() > 0 && + Path[Path.size() - 1] != '\\' && + Path[Path.size() - 1] != ':') { + Path.push_back('\\'); + Path.push_back('*'); + } else { + Path.push_back('*'); + } + + // Get the first directory entry. + WIN32_FIND_DATAA FirstFind; + HANDLE FindHandle(FindFirstFileA(Path.c_str(), &FirstFind)); + if (!FindHandle) + { + Printf("No file found in: %s.\n", Dir.c_str()); + return; + } + + do { + size_t FilenameLen = strlen(FirstFind.cFileName); + if ((FilenameLen == 1 && FirstFind.cFileName[0] == '.') || + (FilenameLen == 2 && FirstFind.cFileName[0] == '.' && + FirstFind.cFileName[1] == '.')) + continue; + + std::string FileName = DirPlusFile(Dir, FirstFind.cFileName); + + HANDLE FileHandle( + CreateFileA(FileName.c_str(), 0, FILE_SHARE_READ, NULL, OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS, 0)); + + BY_HANDLE_FILE_INFORMATION Info; + + if (!GetFileInformationByHandle(FileHandle, &Info)) { + Printf("Couldn't get file info of: %s\n", FileName.c_str()); + CloseHandle(FileHandle); + continue; + } + + if (Info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + ListFilesInDirRecursive(FileName, Epoch, V, false); + else if (GetFileType(FileHandle) == FILE_TYPE_DISK) + V->push_back(FileName); + CloseHandle(FileHandle); + } while (FindNextFileA(FindHandle, &FirstFind)); + + DWORD LastError = GetLastError(); + if (LastError != ERROR_NO_MORE_FILES) + Printf("FindNextFileA failed (Error code: %lu).\n", LastError); + + FindClose(FindHandle); + + if (Epoch && TopDir) + *Epoch = E; +} + +std::string DirPlusFile(const std::string &DirPath, + const std::string &FileName) { + return DirPath + "\\" + FileName; +} + +void DupAndCloseStderr() { + int OutputFd = _dup(2); + if (OutputFd > 0) { + FILE *NewOutputFile = _fdopen(OutputFd, "w"); + if (NewOutputFile) { + OutputFile = NewOutputFile; + if (EF->__sanitizer_set_report_fd) + EF->__sanitizer_set_report_fd(reinterpret_cast(OutputFd)); + _close(2); + } + } +} + +void CloseStdout() { + _close(1); +} + +void Printf(const char *Fmt, ...) { + va_list ap; + va_start(ap, Fmt); + vfprintf(OutputFile, Fmt, ap); + va_end(ap); + fflush(OutputFile); +} + +} // namespace fuzzer +#endif // LIBFUZZER_WINDOWS Index: lib/Fuzzer/FuzzerUtil.cpp =================================================================== --- lib/Fuzzer/FuzzerUtil.cpp +++ lib/Fuzzer/FuzzerUtil.cpp @@ -12,17 +12,13 @@ #include "FuzzerInternal.h" #include #include -#include -#include #include -#include #include #include #include #include #include #include -#include #include #include @@ -73,80 +69,6 @@ return Sha1ToString(Hash); } -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++) { @@ -242,12 +164,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" @@ -276,21 +192,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]; @@ -307,14 +208,4 @@ Printf(FallbackFMT, PC); } -bool ExecuteCommandAndReadOutput(const std::string &Command, std::string *Out) { - FILE *Pipe = popen(Command.c_str(), "r"); - if (!Pipe) return false; - char Buff[1024]; - size_t N; - while ((N = fread(Buff, 1, sizeof(Buff), Pipe)) > 0) - Out->append(Buff, N); - return true; -} - } // namespace fuzzer Index: lib/Fuzzer/FuzzerUtilLinux.cpp =================================================================== --- lib/Fuzzer/FuzzerUtilLinux.cpp +++ lib/Fuzzer/FuzzerUtilLinux.cpp @@ -1,4 +1,4 @@ -//===- FuzzerUtilLinux.cpp - Misc utils -----------------------------------===// +//===- FuzzerUtilLinux.cpp - Misc utils for Linux -------------------------===// // // The LLVM Compiler Infrastructure // Index: lib/Fuzzer/FuzzerUtilPosix.cpp =================================================================== --- lib/Fuzzer/FuzzerUtilPosix.cpp +++ lib/Fuzzer/FuzzerUtilPosix.cpp @@ -0,0 +1,139 @@ +//===- 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 +#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); } + +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; +} + +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; +} + +bool ExecuteCommandAndReadOutput(const std::string &Command, std::string *Out) { + FILE *Pipe = popen(Command.c_str(), "r"); + if (!Pipe) return false; + char Buff[1024]; + size_t N; + while ((N = fread(Buff, 1, sizeof(Buff), Pipe)) > 0) + Out->append(Buff, N); + return true; +} + +} // namespace fuzzer +#endif // LIBFUZZER_POSIX Index: lib/Fuzzer/FuzzerUtilWindows.cpp =================================================================== --- lib/Fuzzer/FuzzerUtilWindows.cpp +++ lib/Fuzzer/FuzzerUtilWindows.cpp @@ -0,0 +1,216 @@ +//===- 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 +#include +#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); + } +} + +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; +} + +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; +} + +bool ExecuteCommandAndReadOutput(const std::string &Command, std::string *Out) { + FILE *Pipe = _popen(Command.c_str(), "r"); + if (!Pipe) return false; + char Buff[1024]; + size_t N; + while ((N = fread(Buff, 1, sizeof(Buff), Pipe)) > 0) + Out->append(Buff, N); + return true; +} + +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