132 cmds = shlex.split(dartfuzz_cmd) + [dart_test] + \
133 [
'--mini',
'--smask',
'%d' % smask,
'--emask',
'%d' % mask]
134 p = subprocess.Popen(cmds, stdout=subprocess.PIPE)
137 cmds = shlex.split(dartfuzz_cmd) + [dart_test] + \
138 [
'--mini',
'--smask',
'%d' % mask]
139 p = subprocess.Popen(cmds, stdout=subprocess.PIPE)
140 p_stdout, p_stderr = p.communicate()
141 if p.returncode != 0:
142 raise 'Invalid return code on generate %d' % p.returncode
145 mask_new =
int(p_stdout.decode().splitlines()[EXPRESSION_MASK_LINE])
147 mask_new =
int(p_stdout.decode().splitlines()[STATEMENT_MASK_LINE])
152def run_dart(dart_cmd, dart_test, error_match_p, timeout):
153 cmd = [
'timeout', str(timeout)] + shlex.split(dart_cmd) + [dart_test]
154 p = subprocess.Popen(cmd, stderr=subprocess.PIPE, stdout=subprocess.PIPE)
155 p_stdout, p_stderr = p.communicate()
156 if error_match_p.search(p_stdout.decode())
or \
157 error_match_p.search(p_stderr.decode()):
159 if p.returncode != 0:
160 print(
"Warning: error return code %d" % p.returncode)
166def run_dart_mp(dart_cmd, dart_test, error_match_p, tries, nthreads, timeout):
168 return run_dart(dart_cmd, dart_test, error_match_p, timeout)
169 pool = mp.Pool(nthreads)
171 pool.apply_async(run_dart,
172 (dart_cmd, dart_test, error_match_p, timeout))
173 for i
in range(tries)
175 worker_done = [
False for i
in range(tries)]
178 for i, result
in enumerate(results):
182 r = result.get(timeout=0.5)
183 worker_done[i] =
True
189 except mp.TimeoutError:
220 p = subprocess.Popen(
221 dartfuzz_cmd +
" --mini " + dart_test,
223 stdout=subprocess.PIPE)
224 p_stdout, p_stderr = p.communicate()
227 nstmts =
int(p_stdout.decode().splitlines()[EXPRESSION_NUMBER_LINE])
228 mask_gen =
MaskGen(nstmts, emask)
231 nstmts =
int(p_stdout.decode().splitlines()[STATEMENT_NUMBER_LINE])
232 mask_gen =
MaskGen(nstmts, smask)
243 error_match_p1 = re.compile(error_match1)
244 error_match_p2 =
None
245 if error_match2
is not None:
246 error_match_p2 = re.compile(error_match2)
247 for mask
in mask_gen:
249 print(
"Mask: %x" % mask)
251 if cntr % print_every == 0:
253 print(
"Best I could do so far is mask %d/%d" \
254 % (max_bits, nstmts))
256 print(dartfuzz_cmd +
" " + dart_test +
257 " --mini --smask 0x%x --emask 0x%x" % (smask, min_mask))
259 print(dartfuzz_cmd +
" " + dart_test +
260 " --mini --smask 0x%x --emask 0" % (min_mask))
265 mask_new =
generate_dart(dartfuzz_cmd, dart_test, smask, mask, do_expr)
267 err =
run_dart_mp(dart_cmd, dart_test, error_match_p1, tries, threads,
270 print(
"Matched error 1 " + error_match1)
272 if (dart_cmd_ref
is not None)
and (error_match_p2
is not None):
273 err_ref =
run_dart_mp(dart_cmd_ref, dart_test, error_match_p2,
274 tries_ref, threads, timeout)
275 if err_ref
and verbose:
276 print(
"Matched error 2 " + error_match2)
280 mask_gen.update_mask(mask)
283 mask_gen.update_mask(mask_new)
284 max_bits = mask_gen.count_bits()
285 min_mask = mask_gen.mask
288 invMaskNew = mask_gen.mask | (mask_gen.max & ~mask_new)
289 if invMaskNew != mask_gen.mask
and \
290 invMaskNew
not in mask_gen.tested:
292 print(
"Mask: %x (i)" % invMaskNew)
295 err =
run_dart_mp(dart_cmd, dart_test, error_match_p1, tries,
298 print(
"Matched error 1 " + error_match1)
300 if (dart_cmd_ref
is not None)
and (error_match_p2
is not None):
302 error_match_p2, tries_ref, threads,
304 if err_ref
and verbose:
305 print(
"Matched error 2 " + error_match2)
307 mask_gen.update_mask(invMaskNew)
308 mask_gen.update_mask(mask_new)
309 max_bits = mask_gen.count_bits()
310 min_mask = mask_gen.mask
311 last_err = err
and err_ref
313 mask_gen.update_tested(mask_new)
315 print(
"Best I could do is %d/%d" \
319 print(dartfuzz_cmd +
" " + dart_test +
320 " --mini --smask 0x%x --emask 0x%x" % (smask, min_mask))
322 print(dartfuzz_cmd +
" " + dart_test +
323 " --mini --smask 0x%x --emask 0" % (min_mask))
329 parser = argparse.ArgumentParser(
330 description=
'Minimize a generated Dart program ' +
331 ' while maintaining an identified crash or divergence. ' +
332 'A second Dart program can be specified for divergence testing.')
336 help=
"dartfuzz command string "
337 "e.g. dart dartfuzz.dart --no-ffi --no-fp --seed 243123600")
340 help=
"Dart command string "
341 "e.g. ./sdk/out/ReleaseX64/dart",
346 help=
"Dart command string for reference build " +
347 "(in case of divergence testing) " +
"e.g. ./sdk/out/ReleaseX64/dart",
352 help=
"output filename for program generated by "
353 "dartfuzz command and passed to Dart command "
357 help=
"string indicating an error for Dart cmd (no multiline matches)",
362 help=
"string matching the diverging output for the Dart " +
363 "reference command (no multiline matches)",
366 '--smask', help=
"hexadecimal statements mask", default=
"0")
368 '--emask', help=
"hexadecimal expressions mask", default=
"0")
371 choices=[
"s",
"e",
"se"],
373 help=
"minimize statements (s) or expressions (e) or both (se)")
378 help=
'number of retries per run for Dart cmd')
384 help=
'number of retries per run for Dart reference cmd')
389 help=
'number of threads to use for retries')
391 '--timeout', type=int, default=60, help=
'timeout for Dart command')
393 '--verbose', help=
"print intermediate results", action=
"store_true")
394 args = parser.parse_args()
395 timeout = args.timeout
396 do_stmt =
"s" in args.typ
397 do_expr =
"e" in args.typ
398 smask =
int(args.smask, 16)
400 print(
"Minimizing Statements")
401 smask =
minimize(args.dartfuzz, args.dart, args.dart_ref,
402 args.testfile, args.err, args.err_ref, smask,
403 int(args.emask, 16),
False, args.verbose, args.tries,
404 args.tries_ref, args.threads, timeout)
406 print(
"Minimizing Expressions")
407 minimize(args.dartfuzz, args.dart, args.dart_ref,
408 args.testfile, args.err, args.err_ref, smask,
409 int(args.emask, 16),
True, args.verbose, args.tries,
410 args.tries_ref, args.threads, timeout)