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,8 +14,11 @@ #include #include +#include #include "FuzzerDefs.h" +#include "FuzzerIO.h" +#include "FuzzerSHA1.h" #include "FuzzerRandom.h" #include "FuzzerTracePC.h" Index: lib/Fuzzer/FuzzerDefs.h =================================================================== --- lib/Fuzzer/FuzzerDefs.h +++ lib/Fuzzer/FuzzerDefs.h @@ -20,15 +20,23 @@ // Platform detection. #ifdef __linux__ -#define LIBFUZZER_LINUX 1 #define LIBFUZZER_APPLE 0 +#define LIBFUZZER_LINUX 1 +#define LIBFUZZER_WINDOWS 0 #elif __APPLE__ -#define LIBFUZZER_LINUX 0 #define LIBFUZZER_APPLE 1 +#define LIBFUZZER_LINUX 0 +#define LIBFUZZER_WINDOWS 0 +#elif _WIN32 +#define LIBFUZZER_APPLE 0 +#define LIBFUZZER_LINUX 0 +#define LIBFUZZER_WINDOWS 1 #else #error "Support for your platform has not been implemented" #endif +#define LIBFUZZER_POSIX LIBFUZZER_APPLE || LIBFUZZER_LINUX + #ifdef __x86_64 #define ATTRIBUTE_TARGET_POPCNT __attribute__((target("popcnt"))) #else @@ -55,64 +63,8 @@ typedef std::vector Unit; typedef std::vector UnitVector; typedef int (*UserCallback)(const uint8_t *Data, size_t Size); -int FuzzerDriver(int *argc, char ***argv, UserCallback Callback); - -bool IsFile(const std::string &Path); -long GetEpoch(const std::string &Path); -std::string FileToString(const std::string &Path); -Unit FileToVector(const std::string &Path, size_t MaxSize = 0, - bool ExitOnError = true); -void ReadDirToVectorOfUnits(const char *Path, std::vector *V, - long *Epoch, size_t MaxSize, bool ExitOnError); -void WriteToFile(const Unit &U, const std::string &Path); -void CopyFileToErr(const std::string &Path); -void DeleteFile(const std::string &Path); -// Returns "Dir/FileName" or equivalent for the current OS. -std::string DirPlusFile(const std::string &DirPath, - const std::string &FileName); - -void DupAndCloseStderr(); -void CloseStdout(); -void Printf(const char *Fmt, ...); -void PrintHexArray(const Unit &U, const char *PrintAfter = ""); -void PrintHexArray(const uint8_t *Data, size_t Size, - const char *PrintAfter = ""); -void PrintASCII(const uint8_t *Data, size_t Size, const char *PrintAfter = ""); -void PrintASCII(const Unit &U, const char *PrintAfter = ""); - -void PrintPC(const char *SymbolizedFMT, const char *FallbackFMT, uintptr_t PC); -std::string DescribePC(const char *SymbolizedFMT, uintptr_t PC); -std::string Hash(const Unit &U); -void SetTimer(int Seconds); -void SetSigSegvHandler(); -void SetSigBusHandler(); -void SetSigAbrtHandler(); -void SetSigIllHandler(); -void SetSigFpeHandler(); -void SetSigIntHandler(); -void SetSigTermHandler(); -std::string Base64(const Unit &U); -int ExecuteCommand(const std::string &Command); -bool ExecuteCommandAndReadOutput(const std::string &Command, std::string *Out); - -size_t GetPeakRSSMb(); - -// Private copy of SHA1 implementation. -static const int kSHA1NumBytes = 20; -// Computes SHA1 hash of 'Len' bytes in 'Data', writes kSHA1NumBytes to 'Out'. -void ComputeSHA1(const uint8_t *Data, size_t Len, uint8_t *Out); -std::string Sha1ToString(const uint8_t Sha1[kSHA1NumBytes]); - -// Changes U to contain only ASCII (isprint+isspace) characters. -// Returns true iff U has been changed. -bool ToASCII(uint8_t *Data, size_t Size); -bool IsASCII(const Unit &U); -bool IsASCII(const uint8_t *Data, size_t Size); - -int NumberOfCpuCores(); -int GetPid(); -void SleepSeconds(int Seconds); +int FuzzerDriver(int *argc, char ***argv, UserCallback Callback); struct ScopedDoingMyOwnMemmem { ScopedDoingMyOwnMemmem(); Index: lib/Fuzzer/FuzzerDictionary.h =================================================================== --- lib/Fuzzer/FuzzerDictionary.h +++ lib/Fuzzer/FuzzerDictionary.h @@ -12,11 +12,12 @@ #ifndef LLVM_FUZZER_DICTIONARY_H #define LLVM_FUZZER_DICTIONARY_H +#include "FuzzerUtil.h" +#include "FuzzerIO.h" +#include "FuzzerDefs.h" #include #include -#include "FuzzerDefs.h" - namespace fuzzer { // A simple POD sized array of bytes. template class FixedWord { Index: lib/Fuzzer/FuzzerDriver.cpp =================================================================== --- lib/Fuzzer/FuzzerDriver.cpp +++ lib/Fuzzer/FuzzerDriver.cpp @@ -12,6 +12,8 @@ #include "FuzzerCorpus.h" #include "FuzzerInterface.h" #include "FuzzerInternal.h" +#include "FuzzerIO.h" +#include "FuzzerIOPlatform.h" #include "FuzzerMutate.h" #include "FuzzerRandom.h" @@ -22,7 +24,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 +442,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,8 +13,8 @@ //===----------------------------------------------------------------------===// #include "FuzzerDefs.h" #if LIBFUZZER_APPLE - #include "FuzzerExtFunctions.h" +#include "FuzzerIO.h" #include using namespace fuzzer; 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,8 +14,8 @@ //===----------------------------------------------------------------------===// #include "FuzzerDefs.h" #if LIBFUZZER_LINUX - #include "FuzzerExtFunctions.h" +#include "FuzzerIO.h" extern "C" { // Declare these symbols as weak to allow them to be optionally defined. Index: lib/Fuzzer/FuzzerExtFunctionsWindows.cpp =================================================================== --- lib/Fuzzer/FuzzerExtFunctionsWindows.cpp +++ lib/Fuzzer/FuzzerExtFunctionsWindows.cpp @@ -0,0 +1,53 @@ +//===- 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" +#include "FuzzerIO.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.h =================================================================== --- lib/Fuzzer/FuzzerIO.h +++ lib/Fuzzer/FuzzerIO.h @@ -0,0 +1,45 @@ +//===- FuzzerIO.h - Internal header for IO utils ----------------*- C++ -* ===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// IO interface. +//===----------------------------------------------------------------------===// +#ifndef LLVM_FUZZER_IO_H +#define LLVM_FUZZER_IO_H + +#include "FuzzerDefs.h" + +namespace fuzzer { + +long GetEpoch(const std::string &Path); + +Unit FileToVector(const std::string &Path, size_t MaxSize = 0, + bool ExitOnError = true); + +void DeleteFile(const std::string &Path); + +std::string FileToString(const std::string &Path); + +void CopyFileToErr(const std::string &Path); + +void WriteToFile(const Unit &U, const std::string &Path); + +void ReadDirToVectorOfUnits(const char *Path, std::vector *V, + long *Epoch, size_t MaxSize, bool ExitOnError); + +// Returns "Dir/FileName" or equivalent for the current OS. +std::string DirPlusFile(const std::string &DirPath, + const std::string &FileName); + +void DupAndCloseStderr(); + +void CloseStdout(); + +void Printf(const char *Fmt, ...); + +} // namespace fuzzer +#endif // LLVM_FUZZER_IO_H Index: lib/Fuzzer/FuzzerIO.cpp =================================================================== --- lib/Fuzzer/FuzzerIO.cpp +++ lib/Fuzzer/FuzzerIO.cpp @@ -8,28 +8,25 @@ //===----------------------------------------------------------------------===// // IO functions. //===----------------------------------------------------------------------===// +#include "FuzzerIOPlatform.h" +#include "FuzzerIO.h" #include "FuzzerExtFunctions.h" #include "FuzzerDefs.h" -#include +#include +#include +#include #include -#include +#include #include #include +#if LIBFUZZER_POSIX #include -#include -#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 +34,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) { @@ -120,23 +94,25 @@ std::string DirPlusFile(const std::string &DirPath, const std::string &FileName) { - return DirPath + "/" + FileName; + return DirPath + GetSeparator() + FileName; } void DupAndCloseStderr() { - int OutputFd = dup(2); + int OutputFd = DuplicateFile(2); if (OutputFd > 0) { - FILE *NewOutputFile = fdopen(OutputFd, "w"); + FILE *NewOutputFile = OpenFile(OutputFd, "w"); if (NewOutputFile) { OutputFile = NewOutputFile; if (EF->__sanitizer_set_report_fd) EF->__sanitizer_set_report_fd(reinterpret_cast(OutputFd)); - close(2); + CloseFile(2); } } } -void CloseStdout() { close(1); } +void CloseStdout() { + CloseFile(1); +} void Printf(const char *Fmt, ...) { va_list ap; Index: lib/Fuzzer/FuzzerIOPlatform.h =================================================================== --- lib/Fuzzer/FuzzerIOPlatform.h +++ lib/Fuzzer/FuzzerIOPlatform.h @@ -0,0 +1,34 @@ +//===- FuzzerIOPlatform.h - Internal header for IO plat. utils --*- C++ -* ===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Interface for IO platform specific functions. +//===----------------------------------------------------------------------===// +#ifndef LLVM_FUZZER_IO_PLATFORM_H +#define LLVM_FUZZER_IO_PLATFORM_H + +#include +#include + +namespace fuzzer { + +// Platform specific functions. +bool IsFile(const std::string &Path); + +void ListFilesInDirRecursive(const std::string &Dir, long *Epoch, + std::vector *V, bool TopDir); + +char GetSeparator(); + +FILE* OpenFile(int Fd, const char *Mode); + +int CloseFile(int Fd); + +int DuplicateFile(int Fd); + +} // namespace fuzzer +#endif // LLVM_FUZZER_IO_PLATFORM_H Index: lib/Fuzzer/FuzzerIOPosix.cpp =================================================================== --- lib/Fuzzer/FuzzerIOPosix.cpp +++ lib/Fuzzer/FuzzerIOPosix.cpp @@ -0,0 +1,74 @@ +//===- 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 "FuzzerIO.h" +#include +#include +#include +#include +#include +#include +#include +#include + +namespace fuzzer { + +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; +} + +char GetSeparator() { + return '/'; +} + +FILE* OpenFile(int Fd, const char* Mode) { + return fdopen(Fd, Mode); +} + +int CloseFile(int fd) { + return close(fd); +} + +int DuplicateFile(int Fd) { + return dup(Fd); +} + +} // namespace fuzzer +#endif // LIBFUZZER_POSIX Index: lib/Fuzzer/FuzzerIOWindows.cpp =================================================================== --- lib/Fuzzer/FuzzerIOWindows.cpp +++ lib/Fuzzer/FuzzerIOWindows.cpp @@ -0,0 +1,142 @@ +//===- 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 "FuzzerIO.h" +#include +#include +#include +#include +#include +#include +#include +#include + +namespace fuzzer { + +bool IsFile(const std::string &Path) { + DWORD Att = GetFileAttributesA(Path.c_str()); + + if (Att == INVALID_FILE_ATTRIBUTES) { + Printf("GetFileAttributesA() failed for \"%s\" (Error code: %lu).\n", + Path.c_str(), GetLastError()); + return false; + } + + if (Att & FILE_ATTRIBUTE_NORMAL) + return true; + + if (Att & FILE_ATTRIBUTE_DIRECTORY) + return false; + + HANDLE FileHandle( + CreateFileA(Path.c_str(), 0, FILE_SHARE_READ, NULL, OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS, 0)); + + if (FileHandle == INVALID_HANDLE_VALUE) { + Printf("CreateFileA() failed for \"%s\" (Error code: %lu).\n", Path.c_str(), + GetLastError()); + return false; + } + + DWORD FileType = GetFileType(FileHandle); + + if (FileType == FILE_TYPE_UNKNOWN) { + Printf("GetFileType() failed for \"%s\" (Error code: %lu).\n", Path.c_str(), + GetLastError()); + CloseHandle(FileHandle); + return false; + } + + if (FileType != FILE_TYPE_DISK) { + 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); + assert(!Path.empty()); + if (Path.back() != '\\') + Path.push_back('\\'); + Path.push_back('*'); + + // Get the first directory entry. + WIN32_FIND_DATAA FirstFind; + HANDLE FindHandle(FindFirstFileA(Path.c_str(), &FirstFind)); + if (FindHandle == INVALID_HANDLE_VALUE) + { + 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); + + DWORD Att = GetFileAttributesA(FileName.c_str()); + + if (Att == INVALID_FILE_ATTRIBUTES) { + Printf("GetFileAttributesA() failed for \"%s\" (Error code: %lu).\n", + FileName.c_str(), GetLastError()); + FindClose(FindHandle); + return; + } + + if (Att & FILE_ATTRIBUTE_DIRECTORY) + ListFilesInDirRecursive(FileName, Epoch, V, false); + else if (IsFile(FileName)) + V->push_back(FileName); + } 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; +} + +char GetSeparator() { + return '\\'; +} + +FILE* OpenFile(int Fd, const char* Mode) { + return _fdopen(Fd, Mode); +} + +int CloseFile(int Fd) { + return _close(Fd); +} + +int DuplicateFile(int Fd) { + return _dup(Fd); +} + +} // namespace fuzzer +#endif // LIBFUZZER_WINDOWS Index: lib/Fuzzer/FuzzerInternal.h =================================================================== --- lib/Fuzzer/FuzzerInternal.h +++ lib/Fuzzer/FuzzerInternal.h @@ -23,6 +23,7 @@ #include "FuzzerExtFunctions.h" #include "FuzzerInterface.h" #include "FuzzerOptions.h" +#include "FuzzerSHA1.h" #include "FuzzerValueBitMap.h" namespace fuzzer { Index: lib/Fuzzer/FuzzerLoop.cpp =================================================================== --- lib/Fuzzer/FuzzerLoop.cpp +++ lib/Fuzzer/FuzzerLoop.cpp @@ -11,14 +11,15 @@ #include "FuzzerInternal.h" #include "FuzzerCorpus.h" +#include "FuzzerIO.h" #include "FuzzerMutate.h" #include "FuzzerTracePC.h" #include "FuzzerRandom.h" #include #include -#include #include +#include #if defined(__has_include) #if __has_include() Index: lib/Fuzzer/FuzzerMutate.cpp =================================================================== --- lib/Fuzzer/FuzzerMutate.cpp +++ lib/Fuzzer/FuzzerMutate.cpp @@ -9,11 +9,10 @@ // Mutate a test input. //===----------------------------------------------------------------------===// -#include - #include "FuzzerCorpus.h" #include "FuzzerDefs.h" #include "FuzzerExtFunctions.h" +#include "FuzzerIO.h" #include "FuzzerMutate.h" #include "FuzzerOptions.h" Index: lib/Fuzzer/FuzzerSHA1.h =================================================================== --- lib/Fuzzer/FuzzerSHA1.h +++ lib/Fuzzer/FuzzerSHA1.h @@ -0,0 +1,31 @@ +//===- FuzzerSHA1.h - Internal header for the SHA1 utils --------*- C++ -* ===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// SHA1 utils. +//===----------------------------------------------------------------------===// +#ifndef LLVM_FUZZER_SHA1_H +#define LLVM_FUZZER_SHA1_H + +#include "FuzzerDefs.h" +#include +#include + +namespace fuzzer { + +// Private copy of SHA1 implementation. +static const int kSHA1NumBytes = 20; + +// Computes SHA1 hash of 'Len' bytes in 'Data', writes kSHA1NumBytes to 'Out'. +void ComputeSHA1(const uint8_t *Data, size_t Len, uint8_t *Out); + +std::string Sha1ToString(const uint8_t Sha1[kSHA1NumBytes]); + +std::string Hash(const Unit &U); + +} // namespace fuzzer +#endif // LLVM_FUZZER_SHA1_H Index: lib/Fuzzer/FuzzerSHA1.cpp =================================================================== --- lib/Fuzzer/FuzzerSHA1.cpp +++ lib/Fuzzer/FuzzerSHA1.cpp @@ -16,12 +16,15 @@ // For the same reason we do not want to depend on SHA1 from LLVM tree. //===----------------------------------------------------------------------===// +#include "FuzzerSHA1.h" #include "FuzzerDefs.h" /* This code is public-domain - it is based on libcrypt * placed in the public domain by Wei Dai and other contributors. */ +#include +#include #include #include @@ -193,10 +196,27 @@ } // namespace; Added for LibFuzzer +namespace fuzzer { + // The rest is added for LibFuzzer -void fuzzer::ComputeSHA1(const uint8_t *Data, size_t Len, uint8_t *Out) { +void ComputeSHA1(const uint8_t *Data, size_t Len, uint8_t *Out) { sha1nfo s; sha1_init(&s); sha1_write(&s, (const char*)Data, Len); memcpy(Out, sha1_result(&s), HASH_LENGTH); } + +std::string Sha1ToString(const uint8_t Sha1[kSHA1NumBytes]) { + std::stringstream SS; + for (int i = 0; i < kSHA1NumBytes; i++) + SS << std::hex << std::setfill('0') << std::setw(2) << (unsigned)Sha1[i]; + return SS.str(); +} + +std::string Hash(const Unit &U) { + uint8_t Hash[kSHA1NumBytes]; + ComputeSHA1(U.data(), U.size(), Hash); + return Sha1ToString(Hash); +} + +} Index: lib/Fuzzer/FuzzerTracePC.cpp =================================================================== --- lib/Fuzzer/FuzzerTracePC.cpp +++ lib/Fuzzer/FuzzerTracePC.cpp @@ -12,16 +12,16 @@ // //===----------------------------------------------------------------------===// -#include -#include -#include - #include "FuzzerCorpus.h" #include "FuzzerDefs.h" #include "FuzzerDictionary.h" #include "FuzzerExtFunctions.h" +#include "FuzzerIO.h" #include "FuzzerTracePC.h" #include "FuzzerValueBitMap.h" +#include +#include +#include namespace fuzzer { Index: lib/Fuzzer/FuzzerTraceState.cpp =================================================================== --- lib/Fuzzer/FuzzerTraceState.cpp +++ lib/Fuzzer/FuzzerTraceState.cpp @@ -11,15 +11,15 @@ #include "FuzzerInternal.h" #include "FuzzerDictionary.h" +#include "FuzzerIO.h" #include "FuzzerMutate.h" #include "FuzzerRandom.h" #include "FuzzerTracePC.h" - #include #include -#include #include #include +#include namespace fuzzer { Index: lib/Fuzzer/FuzzerUtil.h =================================================================== --- lib/Fuzzer/FuzzerUtil.h +++ lib/Fuzzer/FuzzerUtil.h @@ -0,0 +1,70 @@ +//===- FuzzerUtil.h - Internal header for the Fuzzer Utils ------*- C++ -* ===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Util functions. +//===----------------------------------------------------------------------===// +#ifndef LLVM_FUZZER_UTIL_H +#define LLVM_FUZZER_UTIL_H + +#include "FuzzerDefs.h" + +namespace fuzzer { + +void PrintHexArray(const Unit &U, const char *PrintAfter = ""); + +void PrintHexArray(const uint8_t *Data, size_t Size, + const char *PrintAfter = ""); + +void PrintASCII(const uint8_t *Data, size_t Size, const char *PrintAfter = ""); + +void PrintASCII(const Unit &U, const char *PrintAfter = ""); + +// Changes U to contain only ASCII (isprint+isspace) characters. +// Returns true iff U has been changed. +bool ToASCII(uint8_t *Data, size_t Size); + +bool IsASCII(const Unit &U); + +bool IsASCII(const uint8_t *Data, size_t Size); + +std::string Base64(const Unit &U); + +void PrintPC(const char *SymbolizedFMT, const char *FallbackFMT, uintptr_t PC); + +std::string DescribePC(const char *SymbolizedFMT, uintptr_t PC); + +int NumberOfCpuCores(); + +// Platform specific functions. +void SetTimer(int Seconds); + +void SetSigSegvHandler(); +void SetSigBusHandler(); +void SetSigAbrtHandler(); +void SetSigIllHandler(); +void SetSigFpeHandler(); +void SetSigIntHandler(); +void SetSigTermHandler(); + +void SleepSeconds(int Seconds); + +int GetPid(); + +size_t GetPeakRSSMb(); + +bool ExecuteCommandAndReadOutput(const std::string &Command, std::string *Out); + +int ExecuteCommand(const std::string &Command); + +#if LIBFUZZER_WINDOWS +const void *memmem(const void *haystack, size_t haystacklen, + const void *needle, size_t needlelen); +#endif + +} // namespace fuzzer +#endif // LLVM_FUZZER_UTIL_H Index: lib/Fuzzer/FuzzerUtil.cpp =================================================================== --- lib/Fuzzer/FuzzerUtil.cpp +++ lib/Fuzzer/FuzzerUtil.cpp @@ -9,21 +9,17 @@ // Misc utils. //===----------------------------------------------------------------------===// +#include "FuzzerUtil.h" #include "FuzzerInternal.h" -#include -#include -#include -#include -#include -#include +#include "FuzzerIO.h" #include #include #include -#include +#include #include #include -#include -#include +#include +#include #include namespace fuzzer { @@ -60,93 +56,6 @@ PrintASCII(U.data(), U.size(), PrintAfter); } -std::string Sha1ToString(const uint8_t Sha1[kSHA1NumBytes]) { - std::stringstream SS; - for (int i = 0; i < kSHA1NumBytes; i++) - SS << std::hex << std::setfill('0') << std::setw(2) << (unsigned)Sha1[i]; - return SS.str(); -} - -std::string Hash(const Unit &U) { - uint8_t Hash[kSHA1NumBytes]; - ComputeSHA1(U.data(), U.size(), Hash); - 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 +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" @@ -276,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]; @@ -307,14 +195,14 @@ 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; +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; } } // namespace fuzzer Index: lib/Fuzzer/FuzzerUtilDarwin.cpp =================================================================== --- lib/Fuzzer/FuzzerUtilDarwin.cpp +++ lib/Fuzzer/FuzzerUtilDarwin.cpp @@ -10,6 +10,7 @@ //===----------------------------------------------------------------------===// #include "FuzzerDefs.h" #if LIBFUZZER_APPLE +#include "FuzzerIO.h" #include #include #include 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,105 @@ +//===- 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; +} + +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,205 @@ +//===- 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; +} + +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