32
32
OSSFUZZ_DIR = os .path .dirname (os .path .dirname (os .path .realpath (__file__ )))
33
33
BUILD_DIR = os .path .join (OSSFUZZ_DIR , 'build' )
34
34
35
-
36
35
GLOBAL_ARGS = None
37
36
38
37
def main ():
@@ -46,7 +45,7 @@ def main():
46
45
help = 'do not specify --pull while building an image' )
47
46
parser .add_argument (
48
47
'command' ,
49
- help = 'One of: generate, build_image, build_fuzzers, run_fuzzer, coverage, shell' ,
48
+ help = 'One of: generate, build_image, build_fuzzers, run_fuzzer, coverage, reproduce, shell' ,
50
49
nargs = argparse .REMAINDER )
51
50
global GLOBAL_ARGS
52
51
GLOBAL_ARGS = args = parser .parse_args ()
@@ -65,6 +64,8 @@ def main():
65
64
return run_fuzzer (args .command [1 :])
66
65
elif args .command [0 ] == 'coverage' :
67
66
return coverage (args .command [1 :])
67
+ elif args .command [0 ] == 'reproduce' :
68
+ return reproduce (args .command [1 :])
68
69
elif args .command [0 ] == 'shell' :
69
70
return shell (args .command [1 :])
70
71
else :
@@ -100,6 +101,11 @@ def _check_fuzzer_exists(project_name, fuzzer_name):
100
101
return True
101
102
102
103
104
+ def _get_absolute_path (path ):
105
+ """Returns absolute path with user expansion."""
106
+ return os .path .abspath (os .path .expanduser (path ))
107
+
108
+
103
109
def _get_command_string (command ):
104
110
"""Returns a shell escaped command string."""
105
111
return ' ' .join (pipes .quote (part ) for part in command )
@@ -120,7 +126,7 @@ def _build_image(image_name):
120
126
build_args = []
121
127
if not GLOBAL_ARGS .nopull :
122
128
build_args += ['--pull' ]
123
- build_args += ['-t' , 'ossfuzz/' + image_name , dockerfile_dir ]
129
+ build_args += ['-t' , 'ossfuzz/%s' % image_name , dockerfile_dir ]
124
130
125
131
command = [ 'docker' , 'build' ] + build_args
126
132
print ('Running:' , _get_command_string (command ))
@@ -151,6 +157,8 @@ def build_fuzzers(build_args):
151
157
parser = argparse .ArgumentParser ('helper.py build_fuzzers' )
152
158
parser .add_argument ('-e' , action = 'append' , help = "set environment variable" )
153
159
parser .add_argument ('project_name' )
160
+ parser .add_argument ('source_path' , help = 'path of local source' ,
161
+ nargs = '?' )
154
162
args = parser .parse_args (build_args )
155
163
project_name = args .project_name
156
164
@@ -161,12 +169,20 @@ def build_fuzzers(build_args):
161
169
if args .e :
162
170
env += args .e
163
171
164
- command = (['docker' , 'run' , '--rm' , '-i' , '--cap-add' , 'SYS_PTRACE' ] +
165
- sum ([['-e' , v ] for v in env ], []) +
166
- ['-v' , '%s:/out' % os .path .join (BUILD_DIR , 'out' , project_name ),
167
- '-v' , '%s:/work' % os .path .join (BUILD_DIR , 'work' , project_name ),
168
- '-t' , 'ossfuzz/' + project_name
169
- ])
172
+ command = (
173
+ ['docker' , 'run' , '--rm' , '-i' , '--cap-add' , 'SYS_PTRACE' ] +
174
+ sum ([['-e' , v ] for v in env ], [])
175
+ )
176
+ if args .source_path :
177
+ command += [
178
+ '-v' ,
179
+ '%s:/src/%s' % (_get_absolute_path (args .source_path ), args .project_name )
180
+ ]
181
+ command += [
182
+ '-v' , '%s:/out' % os .path .join (BUILD_DIR , 'out' , project_name ),
183
+ '-v' , '%s:/work' % os .path .join (BUILD_DIR , 'work' , project_name ),
184
+ '-t' , 'ossfuzz/%s' % project_name
185
+ ]
170
186
171
187
print ('Running:' , _get_command_string (command ))
172
188
@@ -209,6 +225,7 @@ def run_fuzzer(run_args):
209
225
pipe = subprocess .Popen (command )
210
226
pipe .communicate ()
211
227
228
+
212
229
def coverage (run_args ):
213
230
"""Runs a fuzzer in the container."""
214
231
parser = argparse .ArgumentParser ('helper.py coverage' )
@@ -236,7 +253,7 @@ def coverage(run_args):
236
253
'-v' , '%s:/out' % os .path .join (BUILD_DIR , 'out' , args .project_name ),
237
254
'-v' , '%s:/cov' % temp_dir ,
238
255
'-w' , '/cov' ,
239
- '-e' , 'ASAN_OPTIONS=coverage=1,detect_leaks=0 ' ,
256
+ '-e' , 'ASAN_OPTIONS=coverage=1' ,
240
257
'-t' , 'ossfuzz/base-runner' ,
241
258
'/out/%s' % args .fuzzer_name ,
242
259
'-max_total_time=%s' % args .run_time
@@ -264,6 +281,38 @@ def coverage(run_args):
264
281
pipe .communicate ()
265
282
266
283
284
+ def reproduce (run_args ):
285
+ """Reproduces a testcase in the container."""
286
+ parser = argparse .ArgumentParser ('helper.py reproduce' )
287
+ parser .add_argument ('project_name' , help = 'name of the project' )
288
+ parser .add_argument ('fuzzer_name' , help = 'name of the fuzzer' )
289
+ parser .add_argument ('testcase_path' , help = 'path of local testcase' )
290
+
291
+ args = parser .parse_args (run_args )
292
+
293
+ if not _check_project_exists (args .project_name ):
294
+ return 1
295
+
296
+ if not _check_fuzzer_exists (args .project_name , args .fuzzer_name ):
297
+ return 1
298
+
299
+ if not _build_image ('base-runner' ):
300
+ return 1
301
+
302
+ command = [
303
+ 'docker' , 'run' , '--rm' , '-i' , '--cap-add' , 'SYS_PTRACE' ,
304
+ '-v' , '%s:/out' % os .path .join (BUILD_DIR , 'out' , args .project_name ),
305
+ '-v' , '%s:/testcase' % _get_absolute_path (args .testcase_path ),
306
+ '-t' , 'ossfuzz/base-runner' ,
307
+ 'reproduce' ,
308
+ '/out/%s' % args .fuzzer_name ,
309
+ ]
310
+
311
+ print ('Running:' , _get_command_string (command ))
312
+ pipe = subprocess .Popen (command )
313
+ pipe .communicate ()
314
+
315
+
267
316
def generate (generate_args ):
268
317
"""Generate empty project files."""
269
318
parser = argparse .ArgumentParser ('helper.py generate' )
@@ -311,7 +360,7 @@ def shell(shell_args):
311
360
'docker' , 'run' , '--rm' , '-i' , '--cap-add' , 'SYS_PTRACE' ,
312
361
'-v' , '%s:/out' % os .path .join (BUILD_DIR , 'out' , args .project_name ),
313
362
'-v' , '%s:/work' % os .path .join (BUILD_DIR , 'work' , args .project_name ),
314
- '-t' , 'ossfuzz/' + args .project_name ,
363
+ '-t' , 'ossfuzz/%s' % args .project_name ,
315
364
'/bin/bash'
316
365
]
317
366
print ('Running:' , _get_command_string (command ))
0 commit comments