From d90e9d0f637b45f234652ec59c6051552df586d1 Mon Sep 17 00:00:00 2001 From: Paul Semel Date: Fri, 7 Feb 2025 14:20:53 +0000 Subject: [PATCH] centipede: create workdir in `prepare` instead of the constructor It turns out that the same class can be used for different fuzzing rounds, and the parent directory of the temp dir is being cleared in between each round. For that reason, we need to re-create a workdir in `prepare`. --- .../_internal/bot/fuzzers/centipede/engine.py | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/clusterfuzz/_internal/bot/fuzzers/centipede/engine.py b/src/clusterfuzz/_internal/bot/fuzzers/centipede/engine.py index b9fb08262f..5f59893fe4 100644 --- a/src/clusterfuzz/_internal/bot/fuzzers/centipede/engine.py +++ b/src/clusterfuzz/_internal/bot/fuzzers/centipede/engine.py @@ -149,7 +149,6 @@ class Engine(engine.Engine): def __init__(self): super().__init__() - self.workdir = self._create_temp_dir('workdir') @property def name(self): @@ -202,7 +201,8 @@ def prepare(self, corpus_dir, target_path, build_dir): # 1. Centipede-readable corpus file; # 2. Centipede-readable feature file; # 3. Crash reproducing inputs. - arguments[constants.WORKDIR_FLAGNAME] = str(self.workdir) + workdir = self._create_temp_dir('workdir') + arguments[constants.WORKDIR_FLAGNAME] = str(workdir) # Directory corpus_dir saves the corpus files required by ClusterFuzz. arguments[constants.CORPUS_DIR_FLAGNAME] = corpus_dir @@ -301,7 +301,12 @@ def fuzz(self, target_path, options, reproducers_dir, max_time): # pylint: disa int(fuzz_result.time_executed))) stats_filename = f'fuzzing-stats-{os.path.basename(target_path)}.000000.csv' - stats_file = os.path.join(self.workdir, stats_filename) + args = fuzzer_options.FuzzerArguments.from_list(options.arguments) + assert args is not None + assert constants.WORKDIR_FLAGNAME in args + + workdir = args[constants.WORKDIR_FLAGNAME] + stats_file = os.path.join(workdir, stats_filename) stats = _parse_centipede_stats(stats_file) if not stats: stats = {} @@ -505,9 +510,10 @@ def minimize_testcase(self, target_path, arguments, input_path, output_path, TimeoutError: If the testcase minimization exceeds max_time. """ runner = _get_runner(target_path) + workdir = self._create_temp_dir('workdir') args = [ f'--binary={target_path}', - f'--workdir={self.workdir}', + f'--workdir={workdir}', f'--minimize_crash={input_path}', f'--num_runs={constants.NUM_RUNS_PER_MINIMIZATION}', '--seed=1', @@ -517,7 +523,7 @@ def minimize_testcase(self, target_path, arguments, input_path, output_path, logs.warning( 'Testcase minimization timed out.', fuzzer_output=result.output) raise TimeoutError('Minimization timed out.') - minimum_testcase = self._get_smallest_crasher(self.workdir) + minimum_testcase = self._get_smallest_crasher(workdir) if minimum_testcase: shutil.copyfile(minimum_testcase, output_path) else: