-
Notifications
You must be signed in to change notification settings - Fork 128
/
fuzzer.h
264 lines (201 loc) · 7.23 KB
/
fuzzer.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
/*
Copyright 2020 Google LLC
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#pragma once
#include <string>
#include <list>
#include <vector>
#include <queue>
#include <unordered_map>
#include "prng.h"
#include "mutex.h"
#include "coverage.h"
#include "instrumentation.h"
#include "minimizer.h"
#include "range.h"
#include "rangetracker.h"
#ifdef linux
#include "sancovinstrumentation.h"
#endif
#include "tinyinstinstrumentation.h"
class PRNG;
class Mutator;
class Instrumentation;
class SampleDelivery;
class MutatorSampleContext;
class Sample;
class CoverageClient;
#define DEFAULT_CRASH_REPRODUCE_RETRIES 10
#define DEFAULT_COVERAGE_REPRODUCE_RETRIES 3
#define DELIVERY_RETRY_TIMES 100
#define MAX_IDENTICAL_CRASHES 4
// save state every 5 minutes
#define FUZZER_SAVE_INERVAL (5 * 60)
#define MIN_SAMPLES_TO_GENERATE 10
class Fuzzer {
public:
void Run(int argc, char **argv);
class ThreadContext {
public:
int thread_id;
Fuzzer *fuzzer;
SampleDelivery *sampleDelivery;
PRNG *prng;
Mutator *mutator;
Instrumentation * instrumentation;
Minimizer* minimizer;
RangeTracker* range_tracker;
// only collected with incremental_coverage=off
Coverage thread_coverage;
//std::string target_cmd;
int target_argc;
char **target_argv;
// a thread-local copy of all samples vector
std::vector<Sample *> all_samples_local;
bool coverage_initialized;
~ThreadContext();
};
void RunFuzzerThread(ThreadContext *tc);
protected:
enum FuzzerState {
RESTORE_NEEDED,
INPUT_SAMPLE_PROCESSING,
SERVER_SAMPLE_PROCESSING,
GENERATING_SAMPLES,
FUZZING,
};
enum JobType {
PROCESS_SAMPLE,
FUZZ,
WAIT,
};
class SampleQueueEntry {
public:
SampleQueueEntry() : sample(NULL), context(NULL),
priority(0), sample_index(0), num_runs(0),
num_crashes(0), num_hangs(0), num_newcoverage(0),
discarded(0) {}
void Save(FILE *fp);
void Load(FILE *fp);
Sample *sample;
std::string sample_filename;
MutatorSampleContext *context;
std::vector<Range> ranges;
double priority;
uint64_t sample_index;
uint64_t num_runs;
uint64_t num_crashes;
uint64_t num_hangs;
uint64_t num_newcoverage;
int32_t discarded;
};
struct CmpEntryPtrs
{
bool operator()(const SampleQueueEntry* lhs, const SampleQueueEntry* rhs) const {
if(lhs->priority == rhs->priority) {
// prefer newer samples
return lhs->sample_index < rhs->sample_index;
}
return lhs->priority < rhs->priority;
}
};
std::vector<Sample *> all_samples;
std::vector<SampleQueueEntry *> all_entries;
std::priority_queue<SampleQueueEntry *, std::vector<SampleQueueEntry *>, CmpEntryPtrs> sample_queue;
struct FuzzerJob {
JobType type;
union {
Sample* sample;
SampleQueueEntry* entry;
};
bool discard_sample;
};
void PrintUsage();
void ParseOptions(int argc, char **argv);
void SetupDirectories();
ThreadContext *CreateThreadContext(int argc, char **argv, int thread_id);
virtual Mutator *CreateMutator(int argc, char **argv, ThreadContext *tc) = 0;
virtual PRNG *CreatePRNG(int argc, char **argv, ThreadContext *tc);
virtual Instrumentation *CreateInstrumentation(int argc, char **argv, ThreadContext *tc);
virtual SampleDelivery* CreateSampleDelivery(int argc, char** argv, ThreadContext* tc);
virtual Minimizer* CreateMinimizer(int argc, char** argv, ThreadContext* tc);
virtual RangeTracker* CreateRangeTracker(int argc, char** argv, ThreadContext* tc);
virtual bool OutputFilter(Sample *original_sample, Sample *output_sample, ThreadContext* tc);
virtual void AdjustSamplePriority(ThreadContext *tc, SampleQueueEntry *entry, int found_new_coverage);
// by default, all return values are interesting
virtual bool IsReturnValueInteresting(uint64_t return_value) { return true; }
virtual bool TrackHotOffsets() { return false; }
void ReplaceTargetCmdArg(ThreadContext *tc, const char *search, const char *replace);
bool MagicOutputFilter(Sample *original_sample, Sample *output_sample, const char *magic, size_t magic_size);
void SaveSample(ThreadContext *tc, Sample *sample, uint32_t init_timeout, uint32_t timeout, Sample *original_sample);
RunResult RunSample(ThreadContext *tc, Sample *sample, int *has_new_coverage, bool trim, bool report_to_server, uint32_t init_timeout, uint32_t timeout, Sample *original_sample);
RunResult RunSampleAndGetCoverage(ThreadContext* tc, Sample* sample, Coverage* coverage, uint32_t init_timeout, uint32_t timeout);
RunResult TryReproduceCrash(ThreadContext* tc, Sample* sample, uint32_t init_timeout, uint32_t timeout);
void MinimizeSample(ThreadContext *tc, Sample *sample, Coverage* stable_coverage, uint32_t init_timeout, uint32_t timeout);
int InterestingSample(ThreadContext *tc, Sample *sample, Coverage *stableCoverage, Coverage *variableCoverage);
void SynchronizeAndGetJob(ThreadContext* tc, FuzzerJob* job);
void JobDone(FuzzerJob* job);
void FuzzJob(ThreadContext* tc, FuzzerJob* job);
void ProcessSample(ThreadContext* tc, FuzzerJob* job);
uint64_t num_crashes;
uint64_t num_unique_crashes;
uint64_t num_hangs;
uint64_t num_samples;
uint64_t num_samples_discarded;
uint64_t num_threads;
uint64_t total_execs;
void SaveState(ThreadContext *tc);
void RestoreState(ThreadContext *tc);
void DumpCoverage();
std::string in_dir;
std::string out_dir;
std::string delivery_dir;
std::string sample_dir;
std::string crash_dir;
std::string hangs_dir;
//std::string target_cmd;
int target_argc;
char **target_argv;
uint32_t timeout;
uint32_t init_timeout;
uint32_t corpus_timeout;
Mutex queue_mutex;
Mutex output_mutex;
Mutex coverage_mutex;
Coverage fuzzer_coverage;
Mutex server_mutex;
CoverageClient *server;
uint64_t last_server_update_time_ms;
uint64_t server_update_interval_ms;
std::list<std::string> input_files;
std::list<Sample *> server_samples;
FuzzerState state;
size_t samples_pending;
bool save_hangs;
double acceptable_hang_ratio;
double acceptable_crash_ratio;
bool minimize_samples;
bool keep_samples_in_memory;
bool track_ranges;
int coverage_reproduce_retries;
int crash_reproduce_retries;
bool clean_target_on_coverage;
bool should_restore_state;
bool dry_run;
bool incremental_coverage;
bool add_all_inputs;
bool dump_coverage;
Mutex crash_mutex;
std::unordered_map<std::string, int> unique_crashes;
uint64_t last_save_time;
SampleTrie sample_trie;
};