Index: llvm/trunk/lib/Fuzzer/CMakeLists.txt =================================================================== --- llvm/trunk/lib/Fuzzer/CMakeLists.txt +++ llvm/trunk/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: llvm/trunk/lib/Fuzzer/FuzzerIO.h =================================================================== --- llvm/trunk/lib/Fuzzer/FuzzerIO.h +++ llvm/trunk/lib/Fuzzer/FuzzerIO.h @@ -15,15 +15,11 @@ namespace fuzzer { -bool IsFile(const std::string &Path); - 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); @@ -43,5 +39,21 @@ void Printf(const char *Fmt, ...); +// 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); + +void DeleteFile(const std::string &Path); + } // namespace fuzzer #endif // LLVM_FUZZER_IO_H Index: llvm/trunk/lib/Fuzzer/FuzzerIO.cpp =================================================================== --- llvm/trunk/lib/Fuzzer/FuzzerIO.cpp +++ llvm/trunk/lib/Fuzzer/FuzzerIO.cpp @@ -11,26 +11,17 @@ #include "FuzzerIO.h" #include "FuzzerDefs.h" #include "FuzzerExtFunctions.h" -#include +#include +#include #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); -} - long GetEpoch(const std::string &Path) { struct stat St; if (stat(Path.c_str(), &St)) @@ -38,29 +29,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) { @@ -79,10 +47,6 @@ return Res; } -void DeleteFile(const std::string &Path) { - unlink(Path.c_str()); -} - std::string FileToString(const std::string &Path) { std::ifstream T(Path); return std::string((std::istreambuf_iterator(T)), @@ -121,23 +85,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: llvm/trunk/lib/Fuzzer/FuzzerIOPosix.cpp =================================================================== --- llvm/trunk/lib/Fuzzer/FuzzerIOPosix.cpp +++ llvm/trunk/lib/Fuzzer/FuzzerIOPosix.cpp @@ -0,0 +1,78 @@ +//===- 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); +} + +void DeleteFile(const std::string &Path) { + unlink(Path.c_str()); +} + +} // namespace fuzzer +#endif // LIBFUZZER_POSIX Index: llvm/trunk/lib/Fuzzer/FuzzerIOWindows.cpp =================================================================== --- llvm/trunk/lib/Fuzzer/FuzzerIOWindows.cpp +++ llvm/trunk/lib/Fuzzer/FuzzerIOWindows.cpp @@ -0,0 +1,143 @@ +//===- 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 { + +static bool IsFile(const std::string &Path, const DWORD &FileAttributes) { + + if (FileAttributes & FILE_ATTRIBUTE_NORMAL) + return true; + + if (FileAttributes & 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; +} + +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; + } + + return IsFile(Path, Att); +} + +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 FindInfo; + HANDLE FindHandle(FindFirstFileA(Path.c_str(), &FindInfo)); + if (FindHandle == INVALID_HANDLE_VALUE) + { + Printf("No file found in: %s.\n", Dir.c_str()); + return; + } + + do { + std::string FileName = DirPlusFile(Dir, FindInfo.cFileName); + + if (FindInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { + size_t FilenameLen = strlen(FindInfo.cFileName); + if ((FilenameLen == 1 && FindInfo.cFileName[0] == '.') || + (FilenameLen == 2 && FindInfo.cFileName[0] == '.' && + FindInfo.cFileName[1] == '.')) + continue; + + ListFilesInDirRecursive(FileName, Epoch, V, false); + } + else if (IsFile(FileName, FindInfo.dwFileAttributes)) + V->push_back(FileName); + } while (FindNextFileA(FindHandle, &FindInfo)); + + 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); +} + +void DeleteFile(const std::string &Path) { + _unlink(Path.c_str()); +} + +} // namespace fuzzer +#endif // LIBFUZZER_WINDOWS