@@ -31,10 +31,14 @@ clang++ afl_driver.cpp test_fuzzer.o afl-llvm-rt.o.o
31
31
rm -rf IN OUT; mkdir IN OUT; echo z > IN/z;
32
32
$AFL_HOME/afl-fuzz -i IN -o OUT ./a.out
33
33
################################################################################
34
- AFL_DRIVER_STDERR_DUPLICATE_FILENAME: Setting this environment variable
35
- *appends* stderr to the file specified. If the file does not exist, it is
36
- created. This is useful for getting stack traces (when using ASAN for example)
37
- or original error messages on hard to reproduce bugs.
34
+ AFL_DRIVER_STDERR_DUPLICATE_FILENAME: Setting this *appends* stderr to the file
35
+ specified. If the file does not exist, it is created. This is useful for getting
36
+ stack traces (when using ASAN for example) or original error messages on hard
37
+ to reproduce bugs. Note that any content written to stderr will be written to
38
+ this file instead of stderr's usual location.
39
+
40
+ AFL_DRIVER_CLOSE_FD_MASK: Similar to libFuzzer's -close_fd_mask behavior option.
41
+ If 1, close stdout at startup. If 2 close stderr; if 3 close both.
38
42
39
43
*/
40
44
#include < assert.h>
@@ -97,16 +101,24 @@ static volatile char suppress_warning2 = AFL_PERSISTENT[0];
97
101
98
102
// Notify AFL about deferred forkserver.
99
103
static volatile char AFL_DEFER_FORKSVR[] = " ##SIG_AFL_DEFER_FORKSRV##" ;
100
- extern " C" void __afl_manual_init ();
104
+ extern " C" void __afl_manual_init ();
101
105
static volatile char suppress_warning1 = AFL_DEFER_FORKSVR[0 ];
102
106
103
107
// Input buffer.
104
108
static const size_t kMaxAflInputSize = 1 << 20 ;
105
109
static uint8_t AflInputBuf[kMaxAflInputSize ];
106
110
111
+ // Use this optionally defined function to output sanitizer messages even if
112
+ // user asks to close stderr.
113
+ __attribute__ ((weak)) extern "C" void __sanitizer_set_report_fd(void *);
114
+
115
+ // Keep track of where stderr content is being written to, so that
116
+ // dup_and_close_stderr can use the correct one.
117
+ static FILE *output_file = stderr;
118
+
107
119
// Experimental feature to use afl_driver without AFL's deferred mode.
108
120
// Needs to run before __afl_auto_init.
109
- __attribute__ ((constructor(0 ))) void __decide_deferred_forkserver(void ) {
121
+ __attribute__ ((constructor(0 ))) static void __decide_deferred_forkserver(void ) {
110
122
if (getenv (" AFL_DRIVER_DONT_DEFER" )) {
111
123
if (unsetenv (" __AFL_DEFER_FORKSRV" )) {
112
124
perror (" Failed to unset __AFL_DEFER_FORKSRV" );
@@ -117,13 +129,13 @@ __attribute__((constructor(0))) void __decide_deferred_forkserver(void) {
117
129
118
130
// If the user asks us to duplicate stderr, then do it.
119
131
static void maybe_duplicate_stderr () {
120
- char * stderr_duplicate_filename =
132
+ char * stderr_duplicate_filename =
121
133
getenv (" AFL_DRIVER_STDERR_DUPLICATE_FILENAME" );
122
134
123
135
if (!stderr_duplicate_filename)
124
136
return ;
125
137
126
- FILE* stderr_duplicate_stream =
138
+ FILE * stderr_duplicate_stream =
127
139
freopen (stderr_duplicate_filename, " a+" , stderr);
128
140
129
141
if (!stderr_duplicate_stream) {
@@ -132,6 +144,54 @@ static void maybe_duplicate_stderr() {
132
144
" Failed to duplicate stderr to AFL_DRIVER_STDERR_DUPLICATE_FILENAME" );
133
145
abort ();
134
146
}
147
+ output_file = stderr_duplicate_stream;
148
+ }
149
+
150
+ // Most of these I/O functions were inspired by/copied from libFuzzer's code.
151
+ static void discard_output (int fd) {
152
+ FILE *temp = fopen (" /dev/null" , " w" );
153
+ if (!temp)
154
+ abort ();
155
+ dup2 (fileno (temp), fd);
156
+ fclose (temp);
157
+ }
158
+
159
+ static void close_stdout () { discard_output (STDOUT_FILENO); }
160
+
161
+ // Prevent the targeted code from writing to "stderr" but allow sanitizers and
162
+ // this driver to do so.
163
+ static void dup_and_close_stderr () {
164
+ int output_fileno = fileno (output_file);
165
+ int output_fd = dup (output_fileno);
166
+ if (output_fd <= 0 )
167
+ abort ();
168
+ FILE *new_output_file = fdopen (output_fd, " w" );
169
+ if (!new_output_file)
170
+ abort ();
171
+ if (!__sanitizer_set_report_fd)
172
+ return ;
173
+ __sanitizer_set_report_fd (reinterpret_cast <void *>(output_fd));
174
+ discard_output (output_fileno);
175
+ }
176
+
177
+ static void Printf (const char *Fmt, ...) {
178
+ va_list ap;
179
+ va_start (ap, Fmt);
180
+ vfprintf (output_file, Fmt, ap);
181
+ va_end (ap);
182
+ fflush (output_file);
183
+ }
184
+
185
+ // Close stdout and/or stderr if user asks for it.
186
+ static void maybe_close_fd_mask () {
187
+ char *fd_mask_str = getenv (" AFL_DRIVER_CLOSE_FD_MASK" );
188
+ if (!fd_mask_str)
189
+ return ;
190
+ int fd_mask = atoi (fd_mask_str);
191
+ if (fd_mask & 2 )
192
+ dup_and_close_stderr ();
193
+ if (fd_mask & 1 )
194
+ close_stdout ();
135
195
}
136
196
137
197
// Define LLVMFuzzerMutate to avoid link failures for targets that use it
@@ -142,7 +202,7 @@ extern "C" size_t LLVMFuzzerMutate(uint8_t *Data, size_t Size, size_t MaxSize) {
142
202
}
143
203
144
204
// Execute any files provided as parameters.
145
- int ExecuteFilesOnyByOne (int argc, char **argv) {
205
+ static int ExecuteFilesOnyByOne (int argc, char **argv) {
146
206
for (int i = 1 ; i < argc; i++) {
147
207
std::ifstream in (argv[i], std::ios::binary);
148
208
in.seekg (0 , in.end );
@@ -161,7 +221,7 @@ int ExecuteFilesOnyByOne(int argc, char **argv) {
161
221
}
162
222
163
223
int main (int argc, char **argv) {
164
- fprintf (stderr,
224
+ Printf (
165
225
" ======================= INFO =========================\n "
166
226
" This binary is built for AFL-fuzz.\n "
167
227
" To run the target function on individual input(s) execute this:\n "
@@ -174,21 +234,21 @@ int main(int argc, char **argv) {
174
234
" re-spawning the process (default: 1000)\n "
175
235
" ======================================================\n " ,
176
236
argv[0 ], argv[0 ], argv[0 ]);
237
+
238
+ maybe_duplicate_stderr ();
239
+ maybe_close_fd_mask ();
177
240
if (LLVMFuzzerInitialize)
178
241
LLVMFuzzerInitialize (&argc, &argv);
179
242
// Do any other expensive one-time initialization here.
180
243
181
- maybe_duplicate_stderr ();
182
-
183
244
if (!getenv (" AFL_DRIVER_DONT_DEFER" ))
184
245
__afl_manual_init ();
185
246
186
247
int N = 1000 ;
187
248
if (argc == 2 && argv[1 ][0 ] == ' -' )
188
249
N = atoi (argv[1 ] + 1 );
189
250
else if (argc == 2 && (N = atoi (argv[1 ])) > 0 )
190
- fprintf (stderr, " WARNING: using the deprecated call style `%s %d`\n " ,
191
- argv[0 ], N);
251
+ Printf (" WARNING: using the deprecated call style `%s %d`\n " , argv[0 ], N);
192
252
else if (argc > 1 )
193
253
return ExecuteFilesOnyByOne (argc, argv);
194
254
@@ -212,5 +272,5 @@ int main(int argc, char **argv) {
212
272
delete[] copy;
213
273
}
214
274
}
215
- fprintf (stderr, " %s: successfully executed %d input(s)\n " , argv[0 ], num_runs);
275
+ Printf ( " %s: successfully executed %d input(s)\n " , argv[0 ], num_runs);
216
276
}
0 commit comments