1 //===- FuzzerIO.cpp - IO utils. -------------------------------------------===//
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-exception
7 //===----------------------------------------------------------------------===//
9 //===----------------------------------------------------------------------===//
11 #include "FuzzerDefs.h"
12 #include "FuzzerExtFunctions.h"
14 #include "FuzzerUtil.h"
20 #include <sys/types.h>
24 static FILE *OutputFile
= stderr
;
26 long GetEpoch(const std::string
&Path
) {
28 if (stat(Path
.c_str(), &St
))
29 return 0; // Can't stat, be conservative.
33 Unit
FileToVector(const std::string
&Path
, size_t MaxSize
, bool ExitOnError
) {
34 std::ifstream
T(Path
, std::ios::binary
);
35 if (ExitOnError
&& !T
) {
36 Printf("No such directory: %s; exiting\n", Path
.c_str());
41 auto EndPos
= T
.tellg();
42 if (EndPos
< 0) return {};
43 size_t FileLen
= EndPos
;
45 FileLen
= std::min(FileLen
, MaxSize
);
49 T
.read(reinterpret_cast<char *>(Res
.data()), FileLen
);
53 std::string
FileToString(const std::string
&Path
) {
54 std::ifstream
T(Path
, std::ios::binary
);
55 return std::string((std::istreambuf_iterator
<char>(T
)),
56 std::istreambuf_iterator
<char>());
59 void CopyFileToErr(const std::string
&Path
) {
60 Printf("%s", FileToString(Path
).c_str());
63 void WriteToFile(const Unit
&U
, const std::string
&Path
) {
64 WriteToFile(U
.data(), U
.size(), Path
);
67 void WriteToFile(const std::string
&Data
, const std::string
&Path
) {
68 WriteToFile(reinterpret_cast<const uint8_t *>(Data
.c_str()), Data
.size(),
72 void WriteToFile(const uint8_t *Data
, size_t Size
, const std::string
&Path
) {
73 // Use raw C interface because this function may be called from a sig handler.
74 FILE *Out
= fopen(Path
.c_str(), "wb");
76 fwrite(Data
, sizeof(Data
[0]), Size
, Out
);
80 void AppendToFile(const std::string
&Data
, const std::string
&Path
) {
81 AppendToFile(reinterpret_cast<const uint8_t *>(Data
.data()), Data
.size(),
85 void AppendToFile(const uint8_t *Data
, size_t Size
, const std::string
&Path
) {
86 FILE *Out
= fopen(Path
.c_str(), "a");
89 fwrite(Data
, sizeof(Data
[0]), Size
, Out
);
93 void ReadDirToVectorOfUnits(const char *Path
, Vector
<Unit
> *V
,
94 long *Epoch
, size_t MaxSize
, bool ExitOnError
) {
95 long E
= Epoch
? *Epoch
: 0;
96 Vector
<std::string
> Files
;
97 ListFilesInDirRecursive(Path
, Epoch
, &Files
, /*TopDir*/true);
99 for (size_t i
= 0; i
< Files
.size(); i
++) {
101 if (Epoch
&& GetEpoch(X
) < E
) continue;
103 if ((NumLoaded
& (NumLoaded
- 1)) == 0 && NumLoaded
>= 1024)
104 Printf("Loaded %zd/%zd files from %s\n", NumLoaded
, Files
.size(), Path
);
105 auto S
= FileToVector(X
, MaxSize
, ExitOnError
);
112 void GetSizedFilesFromDir(const std::string
&Dir
, Vector
<SizedFile
> *V
) {
113 Vector
<std::string
> Files
;
114 ListFilesInDirRecursive(Dir
, 0, &Files
, /*TopDir*/true);
115 for (auto &File
: Files
)
116 if (size_t Size
= FileSize(File
))
117 V
->push_back({File
, Size
});
120 std::string
DirPlusFile(const std::string
&DirPath
,
121 const std::string
&FileName
) {
122 return DirPath
+ GetSeparator() + FileName
;
125 void DupAndCloseStderr() {
126 int OutputFd
= DuplicateFile(2);
128 FILE *NewOutputFile
= OpenFile(OutputFd
, "w");
130 OutputFile
= NewOutputFile
;
131 if (EF
->__sanitizer_set_report_fd
)
132 EF
->__sanitizer_set_report_fd(
133 reinterpret_cast<void *>(GetHandleFromFd(OutputFd
)));
143 void Printf(const char *Fmt
, ...) {
146 vfprintf(OutputFile
, Fmt
, ap
);
151 void VPrintf(bool Verbose
, const char *Fmt
, ...) {
152 if (!Verbose
) return;
155 vfprintf(OutputFile
, Fmt
, ap
);
160 static bool MkDirRecursiveInner(const std::string
&Leaf
) {
161 // Prevent chance of potential infinite recursion
165 const std::string
&Dir
= DirName(Leaf
);
167 if (IsDirectory(Dir
)) {
169 return IsDirectory(Leaf
);
172 bool ret
= MkDirRecursiveInner(Dir
);
174 // Give up early if a previous MkDir failed
179 return IsDirectory(Leaf
);
182 bool MkDirRecursive(const std::string
&Dir
) {
186 if (IsDirectory(Dir
))
189 return MkDirRecursiveInner(Dir
);
192 void RmDirRecursive(const std::string
&Dir
) {
194 Dir
, [](const std::string
&Path
) {},
195 [](const std::string
&Path
) { RmDir(Path
); },
196 [](const std::string
&Path
) { RemoveFile(Path
); });
199 std::string
TempPath(const char *Prefix
, const char *Extension
) {
200 return DirPlusFile(TmpDir(), std::string("libFuzzerTemp.") + Prefix
+
201 std::to_string(GetPid()) + Extension
);
204 } // namespace fuzzer