xref: /aosp_15_r20/external/llvm/lib/Fuzzer/FuzzerIO.cpp (revision 9880d6810fe72a1726cb53787c6711e909410d58)
1*9880d681SAndroid Build Coastguard Worker //===- FuzzerIO.cpp - IO utils. -------------------------------------------===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker //                     The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker // IO functions.
10*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
11*9880d681SAndroid Build Coastguard Worker #include "FuzzerExtFunctions.h"
12*9880d681SAndroid Build Coastguard Worker #include "FuzzerInternal.h"
13*9880d681SAndroid Build Coastguard Worker #include <iterator>
14*9880d681SAndroid Build Coastguard Worker #include <fstream>
15*9880d681SAndroid Build Coastguard Worker #include <dirent.h>
16*9880d681SAndroid Build Coastguard Worker #include <sys/types.h>
17*9880d681SAndroid Build Coastguard Worker #include <sys/stat.h>
18*9880d681SAndroid Build Coastguard Worker #include <unistd.h>
19*9880d681SAndroid Build Coastguard Worker #include <cstdarg>
20*9880d681SAndroid Build Coastguard Worker #include <cstdio>
21*9880d681SAndroid Build Coastguard Worker 
22*9880d681SAndroid Build Coastguard Worker namespace fuzzer {
23*9880d681SAndroid Build Coastguard Worker 
24*9880d681SAndroid Build Coastguard Worker static FILE *OutputFile = stderr;
25*9880d681SAndroid Build Coastguard Worker 
IsFile(const std::string & Path)26*9880d681SAndroid Build Coastguard Worker bool IsFile(const std::string &Path) {
27*9880d681SAndroid Build Coastguard Worker   struct stat St;
28*9880d681SAndroid Build Coastguard Worker   if (stat(Path.c_str(), &St))
29*9880d681SAndroid Build Coastguard Worker     return false;
30*9880d681SAndroid Build Coastguard Worker   return S_ISREG(St.st_mode);
31*9880d681SAndroid Build Coastguard Worker }
32*9880d681SAndroid Build Coastguard Worker 
GetEpoch(const std::string & Path)33*9880d681SAndroid Build Coastguard Worker static long GetEpoch(const std::string &Path) {
34*9880d681SAndroid Build Coastguard Worker   struct stat St;
35*9880d681SAndroid Build Coastguard Worker   if (stat(Path.c_str(), &St))
36*9880d681SAndroid Build Coastguard Worker     return 0;  // Can't stat, be conservative.
37*9880d681SAndroid Build Coastguard Worker   return St.st_mtime;
38*9880d681SAndroid Build Coastguard Worker }
39*9880d681SAndroid Build Coastguard Worker 
ListFilesInDirRecursive(const std::string & Dir,long * Epoch,std::vector<std::string> * V,bool TopDir)40*9880d681SAndroid Build Coastguard Worker static void ListFilesInDirRecursive(const std::string &Dir, long *Epoch,
41*9880d681SAndroid Build Coastguard Worker                                     std::vector<std::string> *V, bool TopDir) {
42*9880d681SAndroid Build Coastguard Worker   auto E = GetEpoch(Dir);
43*9880d681SAndroid Build Coastguard Worker   if (Epoch)
44*9880d681SAndroid Build Coastguard Worker     if (E && *Epoch >= E) return;
45*9880d681SAndroid Build Coastguard Worker 
46*9880d681SAndroid Build Coastguard Worker   DIR *D = opendir(Dir.c_str());
47*9880d681SAndroid Build Coastguard Worker   if (!D) {
48*9880d681SAndroid Build Coastguard Worker     Printf("No such directory: %s; exiting\n", Dir.c_str());
49*9880d681SAndroid Build Coastguard Worker     exit(1);
50*9880d681SAndroid Build Coastguard Worker   }
51*9880d681SAndroid Build Coastguard Worker   while (auto E = readdir(D)) {
52*9880d681SAndroid Build Coastguard Worker     std::string Path = DirPlusFile(Dir, E->d_name);
53*9880d681SAndroid Build Coastguard Worker     if (E->d_type == DT_REG || E->d_type == DT_LNK)
54*9880d681SAndroid Build Coastguard Worker       V->push_back(Path);
55*9880d681SAndroid Build Coastguard Worker     else if (E->d_type == DT_DIR && *E->d_name != '.')
56*9880d681SAndroid Build Coastguard Worker       ListFilesInDirRecursive(Path, Epoch, V, false);
57*9880d681SAndroid Build Coastguard Worker   }
58*9880d681SAndroid Build Coastguard Worker   closedir(D);
59*9880d681SAndroid Build Coastguard Worker   if (Epoch && TopDir)
60*9880d681SAndroid Build Coastguard Worker     *Epoch = E;
61*9880d681SAndroid Build Coastguard Worker }
62*9880d681SAndroid Build Coastguard Worker 
FileToVector(const std::string & Path,size_t MaxSize)63*9880d681SAndroid Build Coastguard Worker Unit FileToVector(const std::string &Path, size_t MaxSize) {
64*9880d681SAndroid Build Coastguard Worker   std::ifstream T(Path);
65*9880d681SAndroid Build Coastguard Worker   if (!T) {
66*9880d681SAndroid Build Coastguard Worker     Printf("No such directory: %s; exiting\n", Path.c_str());
67*9880d681SAndroid Build Coastguard Worker     exit(1);
68*9880d681SAndroid Build Coastguard Worker   }
69*9880d681SAndroid Build Coastguard Worker 
70*9880d681SAndroid Build Coastguard Worker   T.seekg(0, T.end);
71*9880d681SAndroid Build Coastguard Worker   size_t FileLen = T.tellg();
72*9880d681SAndroid Build Coastguard Worker   if (MaxSize)
73*9880d681SAndroid Build Coastguard Worker     FileLen = std::min(FileLen, MaxSize);
74*9880d681SAndroid Build Coastguard Worker 
75*9880d681SAndroid Build Coastguard Worker   T.seekg(0, T.beg);
76*9880d681SAndroid Build Coastguard Worker   Unit Res(FileLen);
77*9880d681SAndroid Build Coastguard Worker   T.read(reinterpret_cast<char *>(Res.data()), FileLen);
78*9880d681SAndroid Build Coastguard Worker   return Res;
79*9880d681SAndroid Build Coastguard Worker }
80*9880d681SAndroid Build Coastguard Worker 
FileToString(const std::string & Path)81*9880d681SAndroid Build Coastguard Worker std::string FileToString(const std::string &Path) {
82*9880d681SAndroid Build Coastguard Worker   std::ifstream T(Path);
83*9880d681SAndroid Build Coastguard Worker   return std::string((std::istreambuf_iterator<char>(T)),
84*9880d681SAndroid Build Coastguard Worker                      std::istreambuf_iterator<char>());
85*9880d681SAndroid Build Coastguard Worker }
86*9880d681SAndroid Build Coastguard Worker 
CopyFileToErr(const std::string & Path)87*9880d681SAndroid Build Coastguard Worker void CopyFileToErr(const std::string &Path) {
88*9880d681SAndroid Build Coastguard Worker   Printf("%s", FileToString(Path).c_str());
89*9880d681SAndroid Build Coastguard Worker }
90*9880d681SAndroid Build Coastguard Worker 
WriteToFile(const Unit & U,const std::string & Path)91*9880d681SAndroid Build Coastguard Worker void WriteToFile(const Unit &U, const std::string &Path) {
92*9880d681SAndroid Build Coastguard Worker   // Use raw C interface because this function may be called from a sig handler.
93*9880d681SAndroid Build Coastguard Worker   FILE *Out = fopen(Path.c_str(), "w");
94*9880d681SAndroid Build Coastguard Worker   if (!Out) return;
95*9880d681SAndroid Build Coastguard Worker   fwrite(U.data(), sizeof(U[0]), U.size(), Out);
96*9880d681SAndroid Build Coastguard Worker   fclose(Out);
97*9880d681SAndroid Build Coastguard Worker }
98*9880d681SAndroid Build Coastguard Worker 
ReadDirToVectorOfUnits(const char * Path,std::vector<Unit> * V,long * Epoch,size_t MaxSize)99*9880d681SAndroid Build Coastguard Worker void ReadDirToVectorOfUnits(const char *Path, std::vector<Unit> *V,
100*9880d681SAndroid Build Coastguard Worker                             long *Epoch, size_t MaxSize) {
101*9880d681SAndroid Build Coastguard Worker   long E = Epoch ? *Epoch : 0;
102*9880d681SAndroid Build Coastguard Worker   std::vector<std::string> Files;
103*9880d681SAndroid Build Coastguard Worker   ListFilesInDirRecursive(Path, Epoch, &Files, /*TopDir*/true);
104*9880d681SAndroid Build Coastguard Worker   size_t NumLoaded = 0;
105*9880d681SAndroid Build Coastguard Worker   for (size_t i = 0; i < Files.size(); i++) {
106*9880d681SAndroid Build Coastguard Worker     auto &X = Files[i];
107*9880d681SAndroid Build Coastguard Worker     if (Epoch && GetEpoch(X) < E) continue;
108*9880d681SAndroid Build Coastguard Worker     NumLoaded++;
109*9880d681SAndroid Build Coastguard Worker     if ((NumLoaded & (NumLoaded - 1)) == 0 && NumLoaded >= 1024)
110*9880d681SAndroid Build Coastguard Worker       Printf("Loaded %zd/%zd files from %s\n", NumLoaded, Files.size(), Path);
111*9880d681SAndroid Build Coastguard Worker     V->push_back(FileToVector(X, MaxSize));
112*9880d681SAndroid Build Coastguard Worker   }
113*9880d681SAndroid Build Coastguard Worker }
114*9880d681SAndroid Build Coastguard Worker 
DirPlusFile(const std::string & DirPath,const std::string & FileName)115*9880d681SAndroid Build Coastguard Worker std::string DirPlusFile(const std::string &DirPath,
116*9880d681SAndroid Build Coastguard Worker                         const std::string &FileName) {
117*9880d681SAndroid Build Coastguard Worker   return DirPath + "/" + FileName;
118*9880d681SAndroid Build Coastguard Worker }
119*9880d681SAndroid Build Coastguard Worker 
DupAndCloseStderr()120*9880d681SAndroid Build Coastguard Worker void DupAndCloseStderr() {
121*9880d681SAndroid Build Coastguard Worker   int OutputFd = dup(2);
122*9880d681SAndroid Build Coastguard Worker   if (OutputFd > 0) {
123*9880d681SAndroid Build Coastguard Worker     FILE *NewOutputFile = fdopen(OutputFd, "w");
124*9880d681SAndroid Build Coastguard Worker     if (NewOutputFile) {
125*9880d681SAndroid Build Coastguard Worker       OutputFile = NewOutputFile;
126*9880d681SAndroid Build Coastguard Worker       if (EF->__sanitizer_set_report_fd)
127*9880d681SAndroid Build Coastguard Worker         EF->__sanitizer_set_report_fd(reinterpret_cast<void *>(OutputFd));
128*9880d681SAndroid Build Coastguard Worker       close(2);
129*9880d681SAndroid Build Coastguard Worker     }
130*9880d681SAndroid Build Coastguard Worker   }
131*9880d681SAndroid Build Coastguard Worker }
132*9880d681SAndroid Build Coastguard Worker 
CloseStdout()133*9880d681SAndroid Build Coastguard Worker void CloseStdout() { close(1); }
134*9880d681SAndroid Build Coastguard Worker 
Printf(const char * Fmt,...)135*9880d681SAndroid Build Coastguard Worker void Printf(const char *Fmt, ...) {
136*9880d681SAndroid Build Coastguard Worker   va_list ap;
137*9880d681SAndroid Build Coastguard Worker   va_start(ap, Fmt);
138*9880d681SAndroid Build Coastguard Worker   vfprintf(OutputFile, Fmt, ap);
139*9880d681SAndroid Build Coastguard Worker   va_end(ap);
140*9880d681SAndroid Build Coastguard Worker   fflush(OutputFile);
141*9880d681SAndroid Build Coastguard Worker }
142*9880d681SAndroid Build Coastguard Worker 
143*9880d681SAndroid Build Coastguard Worker }  // namespace fuzzer
144