1ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines//===- FuzzerIO.cpp - IO utils. -------------------------------------------===// 2ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines// 3ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines// The LLVM Compiler Infrastructure 4ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines// 5ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines// This file is distributed under the University of Illinois Open Source 6ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines// License. See LICENSE.TXT for details. 7ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines// 8ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines//===----------------------------------------------------------------------===// 9ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines// IO functions. 10ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines//===----------------------------------------------------------------------===// 11de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar#include "FuzzerExtFunctions.h" 12ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines#include "FuzzerInternal.h" 13ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines#include <iterator> 14ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines#include <fstream> 15ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines#include <dirent.h> 166948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar#include <sys/types.h> 176948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar#include <sys/stat.h> 186948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar#include <unistd.h> 19f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar#include <cstdarg> 206948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar#include <cstdio> 216948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar 22ebe69fe11e48d322045d5949c83283927a0d790bStephen Hinesnamespace fuzzer { 23ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines 24de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarstatic FILE *OutputFile = stderr; 25de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 26de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarbool IsFile(const std::string &Path) { 27de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar struct stat St; 28de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (stat(Path.c_str(), &St)) 29de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return false; 30de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return S_ISREG(St.st_mode); 31de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar} 32de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 336948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainarstatic long GetEpoch(const std::string &Path) { 346948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar struct stat St; 35f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar if (stat(Path.c_str(), &St)) 36f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar return 0; // Can't stat, be conservative. 376948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar return St.st_mtime; 386948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar} 396948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar 40de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarstatic void ListFilesInDirRecursive(const std::string &Dir, long *Epoch, 41de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar std::vector<std::string> *V, bool TopDir) { 42de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar auto E = GetEpoch(Dir); 43de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (Epoch) 44de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (E && *Epoch >= E) return; 45de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 46ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines DIR *D = opendir(Dir.c_str()); 47f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar if (!D) { 48f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar Printf("No such directory: %s; exiting\n", Dir.c_str()); 49f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar exit(1); 50f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar } 51ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines while (auto E = readdir(D)) { 52de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar std::string Path = DirPlusFile(Dir, E->d_name); 53ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines if (E->d_type == DT_REG || E->d_type == DT_LNK) 54de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar V->push_back(Path); 55de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar else if (E->d_type == DT_DIR && *E->d_name != '.') 56de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar ListFilesInDirRecursive(Path, Epoch, V, false); 57ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines } 58ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines closedir(D); 59de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (Epoch && TopDir) 60de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar *Epoch = E; 61ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines} 62ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines 63de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga NainarUnit FileToVector(const std::string &Path, size_t MaxSize) { 64ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines std::ifstream T(Path); 65f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar if (!T) { 66f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar Printf("No such directory: %s; exiting\n", Path.c_str()); 67f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar exit(1); 68f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar } 69de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 70de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar T.seekg(0, T.end); 71de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar size_t FileLen = T.tellg(); 72de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (MaxSize) 73de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar FileLen = std::min(FileLen, MaxSize); 74de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 75de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar T.seekg(0, T.beg); 76de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Unit Res(FileLen); 77de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar T.read(reinterpret_cast<char *>(Res.data()), FileLen); 78de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return Res; 79ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines} 80ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines 810c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainarstd::string FileToString(const std::string &Path) { 820c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar std::ifstream T(Path); 830c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar return std::string((std::istreambuf_iterator<char>(T)), 840c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar std::istreambuf_iterator<char>()); 850c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar} 860c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar 87ebe69fe11e48d322045d5949c83283927a0d790bStephen Hinesvoid CopyFileToErr(const std::string &Path) { 886948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar Printf("%s", FileToString(Path).c_str()); 89ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines} 90ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines 91ebe69fe11e48d322045d5949c83283927a0d790bStephen Hinesvoid WriteToFile(const Unit &U, const std::string &Path) { 92f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar // Use raw C interface because this function may be called from a sig handler. 93f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar FILE *Out = fopen(Path.c_str(), "w"); 94f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar if (!Out) return; 95f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar fwrite(U.data(), sizeof(U[0]), U.size(), Out); 96f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar fclose(Out); 97ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines} 98ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines 996948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainarvoid ReadDirToVectorOfUnits(const char *Path, std::vector<Unit> *V, 100de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar long *Epoch, size_t MaxSize) { 1016948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar long E = Epoch ? *Epoch : 0; 102de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar std::vector<std::string> Files; 103de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar ListFilesInDirRecursive(Path, Epoch, &Files, /*TopDir*/true); 104de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar size_t NumLoaded = 0; 105de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar for (size_t i = 0; i < Files.size(); i++) { 106de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar auto &X = Files[i]; 107de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (Epoch && GetEpoch(X) < E) continue; 108de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar NumLoaded++; 109de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if ((NumLoaded & (NumLoaded - 1)) == 0 && NumLoaded >= 1024) 110de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Printf("Loaded %zd/%zd files from %s\n", NumLoaded, Files.size(), Path); 111de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar V->push_back(FileToVector(X, MaxSize)); 1126948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar } 113ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines} 114ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines 115ebe69fe11e48d322045d5949c83283927a0d790bStephen Hinesstd::string DirPlusFile(const std::string &DirPath, 116ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines const std::string &FileName) { 117ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines return DirPath + "/" + FileName; 118ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines} 119ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines 120de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarvoid DupAndCloseStderr() { 121de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar int OutputFd = dup(2); 122de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (OutputFd > 0) { 123de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar FILE *NewOutputFile = fdopen(OutputFd, "w"); 124de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (NewOutputFile) { 125de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar OutputFile = NewOutputFile; 126de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (EF->__sanitizer_set_report_fd) 127de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar EF->__sanitizer_set_report_fd(reinterpret_cast<void *>(OutputFd)); 128de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar close(2); 129de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } 130de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } 131de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar} 132de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 133de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarvoid CloseStdout() { close(1); } 134de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 1356948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainarvoid Printf(const char *Fmt, ...) { 1366948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar va_list ap; 1376948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar va_start(ap, Fmt); 138de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar vfprintf(OutputFile, Fmt, ap); 1396948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar va_end(ap); 140de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar fflush(OutputFile); 1416948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar} 1426948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar 143ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines} // namespace fuzzer 144