brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.7 KiB · 54cc4ee Raw
221 lines · cpp
1//===- FuzzerIO.cpp - IO utils. -------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8// IO functions.9//===----------------------------------------------------------------------===//10 11#include "FuzzerDefs.h"12#include "FuzzerExtFunctions.h"13#include "FuzzerIO.h"14#include "FuzzerUtil.h"15#include <algorithm>16#include <cstdarg>17#include <fstream>18#include <iterator>19#include <sys/stat.h>20#include <sys/types.h>21 22namespace fuzzer {23 24static FILE *OutputFile = stderr;25 26FILE *GetOutputFile() {27  return OutputFile;28}29 30void SetOutputFile(FILE *NewOutputFile) {31  OutputFile = NewOutputFile;32}33 34long GetEpoch(const std::string &Path) {35  struct stat St;36  if (stat(Path.c_str(), &St))37    return 0;  // Can't stat, be conservative.38  return St.st_mtime;39}40 41Unit FileToVector(const std::string &Path, size_t MaxSize, bool ExitOnError) {42  std::ifstream T(Path, std::ios::binary);43  if (ExitOnError && !T) {44    Printf("No such directory: %s; exiting\n", Path.c_str());45    exit(1);46  }47 48  T.seekg(0, T.end);49  auto EndPos = T.tellg();50  if (EndPos < 0) return {};51  size_t FileLen = EndPos;52  if (MaxSize)53    FileLen = std::min(FileLen, MaxSize);54 55  T.seekg(0, T.beg);56  Unit Res(FileLen);57  T.read(reinterpret_cast<char *>(Res.data()), FileLen);58  return Res;59}60 61std::string FileToString(const std::string &Path) {62  std::ifstream T(Path, std::ios::binary);63  return std::string((std::istreambuf_iterator<char>(T)),64                     std::istreambuf_iterator<char>());65}66 67void CopyFileToErr(const std::string &Path) {68  Puts(FileToString(Path).c_str());69}70 71void WriteToFile(const Unit &U, const std::string &Path) {72  WriteToFile(U.data(), U.size(), Path);73}74 75void WriteToFile(const std::string &Data, const std::string &Path) {76  WriteToFile(reinterpret_cast<const uint8_t *>(Data.c_str()), Data.size(),77              Path);78}79 80void WriteToFile(const uint8_t *Data, size_t Size, const std::string &Path) {81  // Use raw C interface because this function may be called from a sig handler.82  FILE *Out = fopen(Path.c_str(), "wb");83  if (!Out) return;84  fwrite(Data, sizeof(Data[0]), Size, Out);85  fclose(Out);86}87 88void AppendToFile(const std::string &Data, const std::string &Path) {89  AppendToFile(reinterpret_cast<const uint8_t *>(Data.data()), Data.size(),90               Path);91}92 93void AppendToFile(const uint8_t *Data, size_t Size, const std::string &Path) {94  FILE *Out = fopen(Path.c_str(), "a");95  if (!Out)96    return;97  fwrite(Data, sizeof(Data[0]), Size, Out);98  fclose(Out);99}100 101void ReadDirToVectorOfUnits(const char *Path, std::vector<Unit> *V, long *Epoch,102                            size_t MaxSize, bool ExitOnError,103                            std::vector<std::string> *VPaths) {104  long E = Epoch ? *Epoch : 0;105  std::vector<std::string> Files;106  ListFilesInDirRecursive(Path, Epoch, &Files, /*TopDir*/true);107  size_t NumLoaded = 0;108  for (size_t i = 0; i < Files.size(); i++) {109    auto &X = Files[i];110    if (Epoch && GetEpoch(X) < E) continue;111    NumLoaded++;112    if ((NumLoaded & (NumLoaded - 1)) == 0 && NumLoaded >= 1024)113      Printf("Loaded %zd/%zd files from %s\n", NumLoaded, Files.size(), Path);114    auto S = FileToVector(X, MaxSize, ExitOnError);115    if (!S.empty()) {116      V->push_back(S);117      if (VPaths)118        VPaths->push_back(X);119    }120  }121}122 123void GetSizedFilesFromDir(const std::string &Dir, std::vector<SizedFile> *V) {124  std::vector<std::string> Files;125  ListFilesInDirRecursive(Dir, 0, &Files, /*TopDir*/true);126  for (auto &File : Files)127    if (size_t Size = FileSize(File))128      V->push_back({File, Size});129}130 131std::string DirPlusFile(const std::string &DirPath,132                        const std::string &FileName) {133  return DirPath + GetSeparator() + FileName;134}135 136void DupAndCloseStderr() {137  int OutputFd = DuplicateFile(2);138  if (OutputFd >= 0) {139    FILE *NewOutputFile = OpenFile(OutputFd, "w");140    if (NewOutputFile) {141      OutputFile = NewOutputFile;142      if (EF->__sanitizer_set_report_fd)143        EF->__sanitizer_set_report_fd(144            reinterpret_cast<void *>(GetHandleFromFd(OutputFd)));145      DiscardOutput(2);146    }147  }148}149 150void CloseStdout() {151  DiscardOutput(1);152}153 154void Puts(const char *Str) {155  fputs(Str, OutputFile);156  fflush(OutputFile);157}158 159void Printf(const char *Fmt, ...) {160  va_list ap;161  va_start(ap, Fmt);162  vfprintf(OutputFile, Fmt, ap);163  va_end(ap);164  fflush(OutputFile);165}166 167void VPrintf(bool Verbose, const char *Fmt, ...) {168  if (!Verbose) return;169  va_list ap;170  va_start(ap, Fmt);171  vfprintf(OutputFile, Fmt, ap);172  va_end(ap);173  fflush(OutputFile);174}175 176static bool MkDirRecursiveInner(const std::string &Leaf) {177  // Prevent chance of potential infinite recursion178  if (Leaf == ".")179    return true;180 181  const std::string &Dir = DirName(Leaf);182 183  if (IsDirectory(Dir)) {184    MkDir(Leaf);185    return IsDirectory(Leaf);186  }187 188  bool ret = MkDirRecursiveInner(Dir);189  if (!ret) {190    // Give up early if a previous MkDir failed191    return ret;192  }193 194  MkDir(Leaf);195  return IsDirectory(Leaf);196}197 198bool MkDirRecursive(const std::string &Dir) {199  if (Dir.empty())200    return false;201 202  if (IsDirectory(Dir))203    return true;204 205  return MkDirRecursiveInner(Dir);206}207 208void RmDirRecursive(const std::string &Dir) {209  IterateDirRecursive(210      Dir, [](const std::string &Path) {},211      [](const std::string &Path) { RmDir(Path); },212      [](const std::string &Path) { RemoveFile(Path); });213}214 215std::string TempPath(const char *Prefix, const char *Extension) {216  return DirPlusFile(TmpDir(), std::string("libFuzzerTemp.") + Prefix +217                                   std::to_string(GetPid()) + Extension);218}219 220}  // namespace fuzzer221