Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
Classes | Functions | Variables
minimize Namespace Reference

Classes

class  MaskGen
 

Functions

 generate_dart (dartfuzz_cmd, dart_test, smask, mask, do_expr)
 
 run_dart (dart_cmd, dart_test, error_match_p, timeout)
 
 run_dart_mp (dart_cmd, dart_test, error_match_p, tries, nthreads, timeout)
 
 minimize (dartfuzz_cmd, dart_cmd, dart_cmd_ref, dart_test, error_match1, error_match2, smask, emask, do_expr, verbose, tries, tries_ref, threads, timeout, print_every=32)
 
 main ()
 

Variables

int STATEMENT_MASK_LINE = 0
 
int STATEMENT_NUMBER_LINE = 1
 
int EXPRESSION_MASK_LINE = 2
 
int EXPRESSION_NUMBER_LINE = 3
 

Detailed Description

This script minimizes a program generated by dartfuzz.dart.

Function Documentation

◆ generate_dart()

minimize.generate_dart (   dartfuzz_cmd,
  dart_test,
  smask,
  mask,
  do_expr 
)

Definition at line 129 of file minimize.py.

129def generate_dart(dartfuzz_cmd, dart_test, smask, mask, do_expr):
130 if do_expr:
131 # Minimizing expressions.
132 cmds = shlex.split(dartfuzz_cmd) + [dart_test] + \
133 ['--mini', '--smask', '%d' % smask, '--emask', '%d' % mask]
134 p = subprocess.Popen(cmds, stdout=subprocess.PIPE)
135 else:
136 # Minimizing statements.
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
143 mask_new = 0
144 if do_expr:
145 mask_new = int(p_stdout.decode().splitlines()[EXPRESSION_MASK_LINE])
146 else:
147 mask_new = int(p_stdout.decode().splitlines()[STATEMENT_MASK_LINE])
148 return mask_new
149
150
151# Run the Dart program and check for error (by matching error_match_p).
Type::kYUV Type::kRGBA() int(0.7 *637)

◆ main()

minimize.main ( )

Definition at line 328 of file minimize.py.

328def main():
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.')
333 parser.add_argument(
334 '--dartfuzz',
335 required=True,
336 help="dartfuzz command string "
337 "e.g. dart dartfuzz.dart --no-ffi --no-fp --seed 243123600")
338 parser.add_argument(
339 '--dart',
340 help="Dart command string "
341 "e.g. ./sdk/out/ReleaseX64/dart",
342 required=True)
343 parser.add_argument(
344 '--dart-ref',
345 dest="dart_ref",
346 help="Dart command string for reference build " +
347 "(in case of divergence testing) " + "e.g. ./sdk/out/ReleaseX64/dart",
348 default=None)
349 parser.add_argument(
350 '--testfile',
351 required=True,
352 help="output filename for program generated by "
353 "dartfuzz command and passed to Dart command "
354 "e.g fuzz.dart")
355 parser.add_argument(
356 '--err',
357 help="string indicating an error for Dart cmd (no multiline matches)",
358 required=True)
359 parser.add_argument(
360 '--err-ref',
361 dest="err_ref",
362 help="string matching the diverging output for the Dart " +
363 "reference command (no multiline matches)",
364 default=None)
365 parser.add_argument(
366 '--smask', help="hexadecimal statements mask", default="0")
367 parser.add_argument(
368 '--emask', help="hexadecimal expressions mask", default="0")
369 parser.add_argument(
370 '--typ',
371 choices=["s", "e", "se"],
372 required=True,
373 help="minimize statements (s) or expressions (e) or both (se)")
374 parser.add_argument(
375 '--tries',
376 type=int,
377 default=1,
378 help='number of retries per run for Dart cmd')
379 parser.add_argument(
380 '--tries-ref',
381 type=int,
382 dest='tries_ref',
383 default=1,
384 help='number of retries per run for Dart reference cmd')
385 parser.add_argument(
386 '--threads',
387 type=int,
388 default=4,
389 help='number of threads to use for retries')
390 parser.add_argument(
391 '--timeout', type=int, default=60, help='timeout for Dart command')
392 parser.add_argument(
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)
399 if do_stmt:
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)
405 if do_expr:
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)
411
412
void print(void *str)
Definition bridge.cpp:126
Definition main.py:1

◆ minimize()

minimize.minimize (   dartfuzz_cmd,
  dart_cmd,
  dart_cmd_ref,
  dart_test,
  error_match1,
  error_match2,
  smask,
  emask,
  do_expr,
  verbose,
  tries,
  tries_ref,
  threads,
  timeout,
  print_every = 32 
)

Definition at line 198 of file minimize.py.

212 print_every=32):
213 # Run dartfuzz command once to get the total number of statements
214 # and expressions in the generated program.
215 # Output will look like this:
216 # <Current Statement Mask>
217 # <Number of Statements>
218 # <Current Expression Mask>
219 # <Number of Expressions>
220 p = subprocess.Popen(
221 dartfuzz_cmd + " --mini " + dart_test,
222 shell=True,
223 stdout=subprocess.PIPE)
224 p_stdout, p_stderr = p.communicate()
225 if do_expr:
226 # Minimizing expressions.
227 nstmts = int(p_stdout.decode().splitlines()[EXPRESSION_NUMBER_LINE])
228 mask_gen = MaskGen(nstmts, emask)
229 else:
230 # Minimizing statements.
231 nstmts = int(p_stdout.decode().splitlines()[STATEMENT_NUMBER_LINE])
232 mask_gen = MaskGen(nstmts, smask)
233 # Best mask found so far.
234 min_mask = 0
235 # Maximum number of statements or expressions masked.
236 max_bits = 0
237 # Count number of iterations.
238 cntr = 0
239 # Result of the last run.
240 last_err = True
241 # Compile pattern to match standard output and error for a string
242 # identifying the crash.
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:
248 if (verbose):
249 print("Mask: %x" % mask)
250 cntr += 1
251 if cntr % print_every == 0:
252 cntr = 0
253 print("Best I could do so far is mask %d/%d" \
254 % (max_bits, nstmts))
255 if do_expr:
256 print(dartfuzz_cmd + " " + dart_test +
257 " --mini --smask 0x%x --emask 0x%x" % (smask, min_mask))
258 else:
259 print(dartfuzz_cmd + " " + dart_test +
260 " --mini --smask 0x%x --emask 0" % (min_mask))
261 # The return value mask_new contains the actual mask applied by
262 # dartfuzz. Due to nesting, masking one statement might lead to other
263 # statements being masked as well; mask_new will contain this updated
264 # mask.
265 mask_new = generate_dart(dartfuzz_cmd, dart_test, smask, mask, do_expr)
266 # Run generated Dart program and check for error.
267 err = run_dart_mp(dart_cmd, dart_test, error_match_p1, tries, threads,
268 timeout)
269 if err and verbose:
270 print("Matched error 1 " + error_match1)
271 err_ref = True
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)
277 if err and err_ref:
278 # In case the mask used for generating the Dart program lead to an
279 # error, update the mask generator accordingly.
280 mask_gen.update_mask(mask)
281 # TODO (felih): this line should be enough but there seems to be a
282 # bug in dartfuzz.dart calculating mask_new.
283 mask_gen.update_mask(mask_new)
284 max_bits = mask_gen.count_bits()
285 min_mask = mask_gen.mask
286 elif last_err:
287 # If the last run removed the error try the inverse.
288 invMaskNew = mask_gen.mask | (mask_gen.max & ~mask_new)
289 if invMaskNew != mask_gen.mask and \
290 invMaskNew not in mask_gen.tested:
291 if (verbose):
292 print("Mask: %x (i)" % invMaskNew)
293 mask_new = generate_dart(dartfuzz_cmd, dart_test, smask,
294 invMaskNew, do_expr)
295 err = run_dart_mp(dart_cmd, dart_test, error_match_p1, tries,
296 threads, timeout)
297 if err and verbose:
298 print("Matched error 1 " + error_match1)
299 err_ref = True
300 if (dart_cmd_ref is not None) and (error_match_p2 is not None):
301 err_ref = run_dart_mp(dart_cmd_ref, dart_test,
302 error_match_p2, tries_ref, threads,
303 timeout)
304 if err_ref and verbose:
305 print("Matched error 2 " + error_match2)
306 if err and err_ref:
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
312 # Update the set of tested masks with the one we just tested.
313 mask_gen.update_tested(mask_new)
314
315 print("Best I could do is %d/%d" \
316 % (max_bits,nstmts))
317
318 if do_expr:
319 print(dartfuzz_cmd + " " + dart_test +
320 " --mini --smask 0x%x --emask 0x%x" % (smask, min_mask))
321 else:
322 print(dartfuzz_cmd + " " + dart_test +
323 " --mini --smask 0x%x --emask 0" % (min_mask))
324
325 return min_mask
326
327

◆ run_dart()

minimize.run_dart (   dart_cmd,
  dart_test,
  error_match_p,
  timeout 
)

Definition at line 152 of file minimize.py.

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()):
158 return True
159 if p.returncode != 0:
160 print("Warning: error return code %d" % p.returncode)
161 return False
162
163
164# Run multiple tries of the given dart_cmd and check for errors by matching
165# against error_match_p.

◆ run_dart_mp()

minimize.run_dart_mp (   dart_cmd,
  dart_test,
  error_match_p,
  tries,
  nthreads,
  timeout 
)

Definition at line 166 of file minimize.py.

166def run_dart_mp(dart_cmd, dart_test, error_match_p, tries, nthreads, timeout):
167 if tries == 1:
168 return run_dart(dart_cmd, dart_test, error_match_p, timeout)
169 pool = mp.Pool(nthreads)
170 results = [
171 pool.apply_async(run_dart,
172 (dart_cmd, dart_test, error_match_p, timeout))
173 for i in range(tries)
174 ]
175 worker_done = [False for i in range(tries)]
176 while True:
177 all_done = True
178 for i, result in enumerate(results):
179 if worker_done[i]:
180 continue
181 try:
182 r = result.get(timeout=0.5)
183 worker_done[i] = True
184 if r:
185 pool.close()
186 pool.terminate()
187 pool.join()
188 return True
189 except mp.TimeoutError:
190 all_done = False
191 if all_done:
192 break
193 pool.close()
194 pool.join()
195 return False
196
197

Variable Documentation

◆ EXPRESSION_MASK_LINE

int minimize.EXPRESSION_MASK_LINE = 2

Definition at line 18 of file minimize.py.

◆ EXPRESSION_NUMBER_LINE

int minimize.EXPRESSION_NUMBER_LINE = 3

Definition at line 19 of file minimize.py.

◆ STATEMENT_MASK_LINE

int minimize.STATEMENT_MASK_LINE = 0

Definition at line 16 of file minimize.py.

◆ STATEMENT_NUMBER_LINE

int minimize.STATEMENT_NUMBER_LINE = 1

Definition at line 17 of file minimize.py.