llvm/lib/Fuzzer/FuzzerIO.cpp
Zachary Turner 12889449a8 [LibFuzzer] Add Windows implementations of some IO functions.
This patch moves some posix specific file i/o code into a new
file, FuzzerIOPosix.cpp, and provides implementations for these
functions on Windows in FuzzerIOWindows.cpp.  This is another
incremental step towards getting libfuzzer working on Windows,
although it still should not be expected to be fully working.

Patch by Marcos Pividori
Differential Revision: https://reviews.llvm.org/D27233

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@288275 91177308-0d34-0410-b5e6-96231b3b80d8
2016-11-30 21:44:26 +00:00

117 lines
3.2 KiB
C++

//===- FuzzerIO.cpp - IO utils. -------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// IO functions.
//===----------------------------------------------------------------------===//
#include "FuzzerIO.h"
#include "FuzzerDefs.h"
#include "FuzzerExtFunctions.h"
#include <algorithm>
#include <cstdarg>
#include <fstream>
#include <iterator>
#include <sys/types.h>
#include <sys/stat.h>
namespace fuzzer {
static FILE *OutputFile = stderr;
long GetEpoch(const std::string &Path) {
struct stat St;
if (stat(Path.c_str(), &St))
return 0; // Can't stat, be conservative.
return St.st_mtime;
}
Unit FileToVector(const std::string &Path, size_t MaxSize, bool ExitOnError) {
std::ifstream T(Path);
if (ExitOnError && !T) {
Printf("No such directory: %s; exiting\n", Path.c_str());
exit(1);
}
T.seekg(0, T.end);
size_t FileLen = T.tellg();
if (MaxSize)
FileLen = std::min(FileLen, MaxSize);
T.seekg(0, T.beg);
Unit Res(FileLen);
T.read(reinterpret_cast<char *>(Res.data()), FileLen);
return Res;
}
std::string FileToString(const std::string &Path) {
std::ifstream T(Path);
return std::string((std::istreambuf_iterator<char>(T)),
std::istreambuf_iterator<char>());
}
void CopyFileToErr(const std::string &Path) {
Printf("%s", FileToString(Path).c_str());
}
void WriteToFile(const Unit &U, const std::string &Path) {
// Use raw C interface because this function may be called from a sig handler.
FILE *Out = fopen(Path.c_str(), "w");
if (!Out) return;
fwrite(U.data(), sizeof(U[0]), U.size(), Out);
fclose(Out);
}
void ReadDirToVectorOfUnits(const char *Path, std::vector<Unit> *V,
long *Epoch, size_t MaxSize, bool ExitOnError) {
long E = Epoch ? *Epoch : 0;
std::vector<std::string> Files;
ListFilesInDirRecursive(Path, Epoch, &Files, /*TopDir*/true);
size_t NumLoaded = 0;
for (size_t i = 0; i < Files.size(); i++) {
auto &X = Files[i];
if (Epoch && GetEpoch(X) < E) continue;
NumLoaded++;
if ((NumLoaded & (NumLoaded - 1)) == 0 && NumLoaded >= 1024)
Printf("Loaded %zd/%zd files from %s\n", NumLoaded, Files.size(), Path);
auto S = FileToVector(X, MaxSize, ExitOnError);
if (!S.empty())
V->push_back(S);
}
}
std::string DirPlusFile(const std::string &DirPath,
const std::string &FileName) {
return DirPath + GetSeparator() + FileName;
}
void DupAndCloseStderr() {
int OutputFd = DuplicateFile(2);
if (OutputFd > 0) {
FILE *NewOutputFile = OpenFile(OutputFd, "w");
if (NewOutputFile) {
OutputFile = NewOutputFile;
if (EF->__sanitizer_set_report_fd)
EF->__sanitizer_set_report_fd(reinterpret_cast<void *>(OutputFd));
CloseFile(2);
}
}
}
void CloseStdout() {
CloseFile(1);
}
void Printf(const char *Fmt, ...) {
va_list ap;
va_start(ap, Fmt);
vfprintf(OutputFile, Fmt, ap);
va_end(ap);
fflush(OutputFile);
}
} // namespace fuzzer