10
10
#include < test/util/setup_common.h>
11
11
#include < util/check.h>
12
12
#include < util/sock.h>
13
+ #include < util/time.h>
13
14
15
+ #include < csignal>
14
16
#include < cstdint>
15
17
#include < exception>
16
18
#include < fstream>
@@ -59,6 +61,7 @@ void FuzzFrameworkRegisterTarget(std::string_view name, TypeTestOneInput target,
59
61
Assert (it_ins.second );
60
62
}
61
63
64
+ static std::string_view g_fuzz_target;
62
65
static TypeTestOneInput* g_test_one_input{nullptr };
63
66
64
67
void initialize ()
@@ -92,9 +95,12 @@ void initialize()
92
95
should_abort = true ;
93
96
}
94
97
Assert (!should_abort);
95
- std::string_view fuzz_target{Assert (std::getenv (" FUZZ" ))};
96
- const auto it = FuzzTargets ().find (fuzz_target);
97
- Assert (it != FuzzTargets ().end ());
98
+ g_fuzz_target = Assert (std::getenv (" FUZZ" ));
99
+ const auto it = FuzzTargets ().find (g_fuzz_target);
100
+ if (it == FuzzTargets ().end ()) {
101
+ std::cerr << " No fuzzer for " << g_fuzz_target << " ." << std::endl;
102
+ std::exit (EXIT_FAILURE);
103
+ }
98
104
Assert (!g_test_one_input);
99
105
g_test_one_input = &std::get<0 >(it->second );
100
106
std::get<1 >(it->second )();
@@ -112,6 +118,35 @@ static bool read_stdin(std::vector<uint8_t>& data)
112
118
}
113
119
#endif
114
120
121
+ #if defined(PROVIDE_FUZZ_MAIN_FUNCTION) && !defined(__AFL_LOOP)
122
+ static bool read_file (fs::path p, std::vector<uint8_t >& data)
123
+ {
124
+ uint8_t buffer[1024 ];
125
+ FILE* f = fsbridge::fopen (p, " rb" );
126
+ if (f == nullptr ) return false ;
127
+ do {
128
+ const size_t length = fread (buffer, sizeof (uint8_t ), sizeof (buffer), f);
129
+ if (ferror (f)) return false ;
130
+ data.insert (data.end (), buffer, buffer + length);
131
+ } while (!feof (f));
132
+ fclose (f);
133
+ return true ;
134
+ }
135
+ #endif
136
+
137
+ #if defined(PROVIDE_FUZZ_MAIN_FUNCTION) && !defined(__AFL_LOOP)
138
+ static fs::path g_input_path;
139
+ void signal_handler (int signal)
140
+ {
141
+ if (signal == SIGABRT) {
142
+ std::cerr << " Error processing input " << g_input_path << std::endl;
143
+ } else {
144
+ std::cerr << " Unexpected signal " << signal << " received\n " ;
145
+ }
146
+ std::_Exit (EXIT_FAILURE);
147
+ }
148
+ #endif
149
+
115
150
// This function is used by libFuzzer
116
151
extern " C" int LLVMFuzzerTestOneInput (const uint8_t * data, size_t size)
117
152
{
@@ -151,10 +186,37 @@ int main(int argc, char** argv)
151
186
}
152
187
#else
153
188
std::vector<uint8_t > buffer;
154
- if (!read_stdin (buffer)) {
189
+ if (argc <= 1 ) {
190
+ if (!read_stdin (buffer)) {
191
+ return 0 ;
192
+ }
193
+ test_one_input (buffer);
155
194
return 0 ;
156
195
}
157
- test_one_input (buffer);
196
+ std::signal (SIGABRT, signal_handler);
197
+ int64_t start_time = GetTimeSeconds ();
198
+ int tested = 0 ;
199
+ for (int i = 1 ; i < argc; ++i) {
200
+ fs::path input_path (*(argv + i));
201
+ if (fs::is_directory (input_path)) {
202
+ for (fs::directory_iterator it (input_path); it != fs::directory_iterator (); ++it) {
203
+ if (!fs::is_regular_file (it->path ())) continue ;
204
+ g_input_path = it->path ();
205
+ Assert (read_file (it->path (), buffer));
206
+ test_one_input (buffer);
207
+ ++tested;
208
+ buffer.clear ();
209
+ }
210
+ } else {
211
+ g_input_path = input_path;
212
+ Assert (read_file (input_path, buffer));
213
+ test_one_input (buffer);
214
+ ++tested;
215
+ buffer.clear ();
216
+ }
217
+ }
218
+ int64_t end_time = GetTimeSeconds ();
219
+ std::cout << g_fuzz_target << " : succeeded against " << tested << " files in " << (end_time - start_time) << " s." << std::endl;
158
220
#endif
159
221
return 0 ;
160
222
}
0 commit comments