1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-25 20:23:11 +01:00
llvm-mirror/lib/Fuzzer/FuzzerIO.cpp
Zachary Turner f7c5b2eef9 [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

llvm-svn: 288275
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