1919import os
2020import random
2121import shutil
22- from typing import Dict
2322from typing import List
2423import zipfile
2524
@@ -301,15 +300,16 @@ def _cross_pollinate_other_fuzzer_corpuses(self):
301300
302301class BaseRunner :
303302 """Base Runner"""
303+
304304 def __init__ (self , build_directory , context ):
305305 self .build_directory = build_directory
306306 self .context = context
307-
307+
308308 self .target_path = engine_common .find_fuzzer_path (
309- self .build_directory , self .context .fuzz_target .binary )
309+ self .build_directory , self .context .fuzz_target .binary )
310310 if not self .target_path :
311311 raise CorpusPruningError (
312- f'Failed to get fuzzer path for { self .context .fuzz_target .binary } ' )
312+ f'Failed to get fuzzer path for { self .context .fuzz_target .binary } ' )
313313 self .fuzzer_options = options .get_fuzz_target_options (self .target_path )
314314
315315 def get_fuzzer_flags (self ):
@@ -331,14 +331,17 @@ def process_sanitizer_options(self):
331331 asan_options .update (overrides )
332332 environment .set_memory_tool_options ('ASAN_OPTIONS' , asan_options )
333333
334- def reproduce (self , input_path , arguments , max_time ):
335- return self .context .engine .reproduce (self .target_path , input_path , arguments , max_time )
334+ def reproduce (self , input_path , arguments , max_time ):
335+ return self .context .engine .reproduce (self .target_path , input_path ,
336+ arguments , max_time )
337+
338+ def minimize_corpus (self , arguments , input_dirs , output_dir ,
339+ reproducers_dir , max_time ):
340+ return self .context .engine .minimize_corpus (self .target_path , arguments ,
341+ input_dirs , output_dir ,
342+ reproducers_dir , max_time )
336343
337- def minimize_corpus (self , arguments , input_dirs , output_dir , reproducers_dir , max_time ):
338- return self .context .engine .minimize_corpus (self .target_path , arguments ,
339- input_dirs , output_dir , reproducers_dir , max_time )
340344
341-
342345class LibFuzzerRunner (Runner ):
343346 """Runner for libFuzzer."""
344347
@@ -392,9 +395,10 @@ def minimize_corpus(self, arguments, input_dirs, output_dir, reproducers_dir,
392395class GenericRunner (BaseRunner ):
393396 """Runner implementation for Centipede fuzzing engine."""
394397
395-
398+
396399class CorpusPrunerBase :
397400 """Base class for corpus pruning that is engine‐agnostic."""
401+
398402 def __init__ (self , runner ):
399403 self .runner = runner
400404 self .context = runner .context
@@ -406,36 +410,37 @@ def run(self, initial_corpus_path, minimized_corpus_path, bad_units_path):
406410
407411 # Unpack seed corpus if needed.
408412 engine_common .unpack_seed_corpus_if_needed (
409- self .runner .target_path , initial_corpus_path , force_unpack = True )
413+ self .runner .target_path , initial_corpus_path , force_unpack = True )
410414
411415 environment .reset_current_memory_tool_options (
412- redzone_size = MIN_REDZONE , leaks = True )
416+ redzone_size = MIN_REDZONE , leaks = True )
413417 self .runner .process_sanitizer_options ()
414418
415419 additional_args = self .runner .get_fuzzer_flags ()
416420 logs .info ('Running merge...' )
417421 try :
418422 result = self .runner .minimize_corpus (
419- additional_args , [initial_corpus_path ], minimized_corpus_path ,
420- bad_units_path , CORPUS_PRUNING_TIMEOUT )
423+ additional_args , [initial_corpus_path ], minimized_corpus_path ,
424+ bad_units_path , CORPUS_PRUNING_TIMEOUT )
421425 except TimeoutError as e :
422426 raise CorpusPruningError (
423- 'Corpus pruning timed out while minimizing corpus\n ' + repr (e ))
427+ 'Corpus pruning timed out while minimizing corpus\n ' + repr (e ))
424428 except engine .Error as e :
425- raise CorpusPruningError (
426- 'Corpus pruning failed to minimize corpus \n ' + repr (e ))
429+ raise CorpusPruningError ('Corpus pruning failed to minimize corpus \n ' +
430+ repr (e ))
427431
428432 symbolized_output = stack_symbolizer .symbolize_stacktrace (result .logs )
429433
430434 if not shell .get_directory_file_count (minimized_corpus_path ):
431435 raise CorpusPruningError ('Corpus pruning failed to minimize corpus\n ' +
432- symbolized_output )
436+ symbolized_output )
433437
434- logs .info ('Corpus merge finished successfully.' ,
435- output = symbolized_output )
438+ logs .info ('Corpus merge finished successfully.' , output = symbolized_output )
436439 return result .stats
437440
438441 def process_bad_units (self , bad_units_path , quarantine_corpus_path ):
442+ del bad_units_path
443+ del quarantine_corpus_path
439444 return {}
440445
441446
@@ -444,13 +449,14 @@ class LibFuzzerPruner(CorpusPrunerBase):
444449 LibFuzzerPruner is a specialized pruner for libFuzzer that handles
445450 quarantining of problematic units and related special cases.
446451 """
452+
447453 def _run_single_unit (self , unit_path ):
448454 arguments = self .runner .get_fuzzer_flags () # Expect libFuzzer flags.
449455 return self .runner .reproduce (unit_path , arguments , SINGLE_UNIT_TIMEOUT )
450456
451457 def _quarantine_unit (self , unit_path , quarantine_corpus_path ):
452- quarantined_unit_path = os .path .join (
453- quarantine_corpus_path , os .path .basename (unit_path ))
458+ quarantined_unit_path = os .path .join (quarantine_corpus_path ,
459+ os .path .basename (unit_path ))
454460 shutil .move (unit_path , quarantined_unit_path )
455461 return quarantined_unit_path
456462
@@ -501,18 +507,19 @@ def process_bad_units(self, bad_units_path, quarantine_corpus_path):
501507
502508 if state .crash_state not in crashes :
503509 security_flag = crash_analyzer .is_security_issue (
504- state .crash_stacktrace , state .crash_type , state .crash_address )
505- crashes [state .crash_state ] = uworker_msg_pb2 .CrashInfo (
506- crash_state = state .crash_state ,
507- crash_type = state .crash_type ,
508- crash_address = state .crash_address ,
509- crash_stacktrace = state .crash_stacktrace ,
510- unit_path = unit_path ,
511- security_flag = security_flag )
512- logs .info ('Found %d bad units, %d unique crashes.' %
513- ( num_bad_units , len (crashes )))
510+ state .crash_stacktrace , state .crash_type , state .crash_address )
511+ crashes [state .crash_state ] = uworker_msg_pb2 .CrashInfo ( # pylint: disable=no-member
512+ crash_state = state .crash_state ,
513+ crash_type = state .crash_type ,
514+ crash_address = state .crash_address ,
515+ crash_stacktrace = state .crash_stacktrace ,
516+ unit_path = unit_path ,
517+ security_flag = security_flag )
518+ logs .info ('Found %d bad units, %d unique crashes.' % ( num_bad_units ,
519+ len (crashes )))
514520 return crashes
515521
522+
516523class GenericPruner (BasePruner ):
517524 """Generic pruner."""
518525
@@ -607,7 +614,6 @@ def _record_cross_pollination_stats(output):
607614 client = big_query .Client (
608615 dataset_id = 'main' , table_id = 'cross_pollination_statistics' )
609616 client .insert ([big_query .Insert (row = bigquery_row , insert_id = None )])
610-
611617
612618
613619def do_corpus_pruning (uworker_input , context , revision ) -> CorpusPruningResult :
0 commit comments