/src/mozilla-central/tools/fuzzing/libfuzzer/FuzzerIO.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //===- FuzzerIO.cpp - IO utils. -------------------------------------------===// |
2 | | // |
3 | | // The LLVM Compiler Infrastructure |
4 | | // |
5 | | // This file is distributed under the University of Illinois Open Source |
6 | | // License. See LICENSE.TXT for details. |
7 | | // |
8 | | //===----------------------------------------------------------------------===// |
9 | | // IO functions. |
10 | | //===----------------------------------------------------------------------===// |
11 | | |
12 | | #include "FuzzerIO.h" |
13 | | #include "FuzzerDefs.h" |
14 | | #include "FuzzerExtFunctions.h" |
15 | | #include <algorithm> |
16 | | #include <cstdarg> |
17 | | #include <fstream> |
18 | | #include <iterator> |
19 | | #include <sys/stat.h> |
20 | | #include <sys/types.h> |
21 | | |
22 | | namespace fuzzer { |
23 | | |
24 | | static FILE *OutputFile = stderr; |
25 | | |
26 | 6 | long GetEpoch(const std::string &Path) { |
27 | 6 | struct stat St; |
28 | 6 | if (stat(Path.c_str(), &St)) |
29 | 0 | return 0; // Can't stat, be conservative. |
30 | 6 | return St.st_mtime; |
31 | 6 | } |
32 | | |
33 | 16.2k | Unit FileToVector(const std::string &Path, size_t MaxSize, bool ExitOnError) { |
34 | 16.2k | std::ifstream T(Path); |
35 | 16.2k | if (ExitOnError && !T) { |
36 | 0 | Printf("No such directory: %s; exiting\n", Path.c_str()); |
37 | 0 | exit(1); |
38 | 0 | } |
39 | 16.2k | |
40 | 16.2k | T.seekg(0, T.end); |
41 | 16.2k | auto EndPos = T.tellg(); |
42 | 16.2k | if (EndPos < 0) return {}; |
43 | 16.2k | size_t FileLen = EndPos; |
44 | 16.2k | if (MaxSize) |
45 | 16.2k | FileLen = std::min(FileLen, MaxSize); |
46 | 16.2k | |
47 | 16.2k | T.seekg(0, T.beg); |
48 | 16.2k | Unit Res(FileLen); |
49 | 16.2k | T.read(reinterpret_cast<char *>(Res.data()), FileLen); |
50 | 16.2k | return Res; |
51 | 16.2k | } |
52 | | |
53 | 0 | std::string FileToString(const std::string &Path) { |
54 | 0 | std::ifstream T(Path); |
55 | 0 | return std::string((std::istreambuf_iterator<char>(T)), |
56 | 0 | std::istreambuf_iterator<char>()); |
57 | 0 | } |
58 | | |
59 | 0 | void CopyFileToErr(const std::string &Path) { |
60 | 0 | Printf("%s", FileToString(Path).c_str()); |
61 | 0 | } |
62 | | |
63 | 0 | void WriteToFile(const Unit &U, const std::string &Path) { |
64 | 0 | // Use raw C interface because this function may be called from a sig handler. |
65 | 0 | FILE *Out = fopen(Path.c_str(), "w"); |
66 | 0 | if (!Out) return; |
67 | 0 | fwrite(U.data(), sizeof(U[0]), U.size(), Out); |
68 | 0 | fclose(Out); |
69 | 0 | } |
70 | | |
71 | | void ReadDirToVectorOfUnits(const char *Path, Vector<Unit> *V, |
72 | 0 | long *Epoch, size_t MaxSize, bool ExitOnError) { |
73 | 0 | long E = Epoch ? *Epoch : 0; |
74 | 0 | Vector<std::string> Files; |
75 | 0 | ListFilesInDirRecursive(Path, Epoch, &Files, /*TopDir*/true); |
76 | 0 | size_t NumLoaded = 0; |
77 | 0 | for (size_t i = 0; i < Files.size(); i++) { |
78 | 0 | auto &X = Files[i]; |
79 | 0 | if (Epoch && GetEpoch(X) < E) continue; |
80 | 0 | NumLoaded++; |
81 | 0 | if ((NumLoaded & (NumLoaded - 1)) == 0 && NumLoaded >= 1024) |
82 | 0 | Printf("Loaded %zd/%zd files from %s\n", NumLoaded, Files.size(), Path); |
83 | 0 | auto S = FileToVector(X, MaxSize, ExitOnError); |
84 | 0 | if (!S.empty()) |
85 | 0 | V->push_back(S); |
86 | 0 | } |
87 | 0 | } |
88 | | |
89 | | |
90 | 3 | void GetSizedFilesFromDir(const std::string &Dir, Vector<SizedFile> *V) { |
91 | 3 | Vector<std::string> Files; |
92 | 3 | ListFilesInDirRecursive(Dir, 0, &Files, /*TopDir*/true); |
93 | 3 | for (auto &File : Files) |
94 | 16.2k | if (size_t Size = FileSize(File)) |
95 | 16.2k | V->push_back({File, Size}); |
96 | 3 | } |
97 | | |
98 | | std::string DirPlusFile(const std::string &DirPath, |
99 | 16.2k | const std::string &FileName) { |
100 | 16.2k | return DirPath + GetSeparator() + FileName; |
101 | 16.2k | } |
102 | | |
103 | 3 | void DupAndCloseStderr() { |
104 | 3 | int OutputFd = DuplicateFile(2); |
105 | 3 | if (OutputFd > 0) { |
106 | 3 | FILE *NewOutputFile = OpenFile(OutputFd, "w"); |
107 | 3 | if (NewOutputFile) { |
108 | 3 | OutputFile = NewOutputFile; |
109 | 3 | if (EF->__sanitizer_set_report_fd) |
110 | 3 | EF->__sanitizer_set_report_fd( |
111 | 3 | reinterpret_cast<void *>(GetHandleFromFd(OutputFd))); |
112 | 3 | DiscardOutput(2); |
113 | 3 | } |
114 | 3 | } |
115 | 3 | } |
116 | | |
117 | 3 | void CloseStdout() { |
118 | 3 | DiscardOutput(1); |
119 | 3 | } |
120 | | |
121 | 159 | void Printf(const char *Fmt, ...) { |
122 | 159 | va_list ap; |
123 | 159 | va_start(ap, Fmt); |
124 | 159 | vfprintf(OutputFile, Fmt, ap); |
125 | 159 | va_end(ap); |
126 | 159 | fflush(OutputFile); |
127 | 159 | } |
128 | | |
129 | | } // namespace fuzzer |