mirror of
https://github.com/RPCSX/llvm.git
synced 2024-12-23 04:28:40 +00:00
12889449a8
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
117 lines
3.2 KiB
C++
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
|