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