Index: lib/Fuzzer/CMakeLists.txt =================================================================== --- lib/Fuzzer/CMakeLists.txt +++ lib/Fuzzer/CMakeLists.txt @@ -10,15 +10,17 @@ endif() add_library(LLVMFuzzerNoMainObjects OBJECT FuzzerCrossOver.cpp - FuzzerTraceState.cpp FuzzerDriver.cpp FuzzerExtFunctionsDlsym.cpp FuzzerExtFunctionsWeak.cpp FuzzerIO.cpp + FuzzerIOPosix.cpp + FuzzerIOWindows.cpp FuzzerLoop.cpp FuzzerMutate.cpp FuzzerSHA1.cpp FuzzerTracePC.cpp + FuzzerTraceState.cpp FuzzerUtil.cpp FuzzerUtilDarwin.cpp FuzzerUtilLinux.cpp Index: lib/Fuzzer/FuzzerDriver.cpp =================================================================== --- lib/Fuzzer/FuzzerDriver.cpp +++ lib/Fuzzer/FuzzerDriver.cpp @@ -13,6 +13,7 @@ #include "FuzzerInterface.h" #include "FuzzerInternal.h" #include "FuzzerIO.h" +#include "FuzzerIOPlatform.h" #include "FuzzerMutate.h" #include "FuzzerRandom.h" Index: lib/Fuzzer/FuzzerIO.h =================================================================== --- lib/Fuzzer/FuzzerIO.h +++ lib/Fuzzer/FuzzerIO.h @@ -41,18 +41,5 @@ void Printf(const char *Fmt, ...); -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_H Index: lib/Fuzzer/FuzzerIO.cpp =================================================================== --- lib/Fuzzer/FuzzerIO.cpp +++ lib/Fuzzer/FuzzerIO.cpp @@ -8,29 +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)) @@ -38,29 +34,6 @@ return St.st_mtime; } -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) { @@ -121,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 =================================================================== --- /dev/null +++ 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 =================================================================== --- /dev/null +++ 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 =================================================================== --- /dev/null +++ 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