def test_get_invalid_project(self): """Checks the latest build will return None when project doesn't exist.""" test_target = fuzz_target.FuzzTarget('/example/path', 10, '/example/outdir', 'not-a-proj') self.assertIsNone(test_target.get_lastest_build_version()) test_target = fuzz_target.FuzzTarget('/example/path', 10, '/example/outdir') self.assertIsNone(test_target.get_lastest_build_version())
def test_get_invalid_project(self): """Tests the latest build returns None when project doesn't exist.""" with tempfile.TemporaryDirectory() as tmp_dir: test_target = fuzz_target.FuzzTarget('/example/do_stuff_fuzzer', 10, tmp_dir) self.assertIsNone(test_target.download_oss_fuzz_build()) test_target = fuzz_target.FuzzTarget('/example/do_stuff_fuzzer', 10, tmp_dir, 'not-a-proj') self.assertIsNone(test_target.download_oss_fuzz_build())
def test_download_invalid_projects_corpus(self): """Tests that a invaild fuzz target does not return None.""" with tempfile.TemporaryDirectory() as tmp_dir: test_target = fuzz_target.FuzzTarget('testfuzzer', 3, tmp_dir) corpus_path = test_target.download_latest_corpus() self.assertIsNone(corpus_path) test_target = fuzz_target.FuzzTarget('not_a_fuzzer', 3, tmp_dir, 'not_a_project') corpus_path = test_target.download_latest_corpus() self.assertIsNone(corpus_path)
def setUp(self): """Sets up example fuzz target to test get_testcase method.""" deployment = _create_deployment() self.test_target = fuzz_target.FuzzTarget('/example/path', 10, '/example/outdir', deployment, deployment.config)
def test_invalid_build_dir(self): """Tests the download returns None when out_dir doesn't exist.""" with tempfile.TemporaryDirectory() as tmp_dir: invalid_dir = os.path.join(tmp_dir, 'not/a/dir') test_target = fuzz_target.FuzzTarget('/example/do_stuff_fuzzer', 10, invalid_dir, 'example') self.assertIsNone(test_target.download_oss_fuzz_build())
def setUp(self): """Sets up dummy fuzz target to test is_reproducible method.""" self.fuzz_target_path = '/example/path' self.testcase_path = '/testcase' self.test_target = fuzz_target.FuzzTarget( self.fuzz_target_path, fuzz_target.REPRODUCE_ATTEMPTS, '/example/outdir')
def create_fuzz_target_obj(self, target_path, run_seconds): """Returns a fuzz target object.""" return fuzz_target.FuzzTarget(target_path, run_seconds, self.out_dir, self.config.project_name, sanitizer=self.config.sanitizer)
def run_fuzzers(config): # pylint: disable=too-many-locals """Runs fuzzers for a specific OSS-Fuzz project. Args: fuzz_seconds: The total time allotted for fuzzing. workspace: The location in a shared volume to store a git repo and build artifacts. project_name: The name of the relevant OSS-Fuzz project. sanitizer: The sanitizer the fuzzers should be run with. Returns: (True if run was successful, True if bug was found). """ # Validate inputs. logging.info('Using %s sanitizer.', config.sanitizer) out_dir = os.path.join(config.workspace, 'out') artifacts_dir = os.path.join(out_dir, 'artifacts') os.makedirs(artifacts_dir, exist_ok=True) if not config.fuzz_seconds or config.fuzz_seconds < 1: logging.error( 'Fuzz_seconds argument must be greater than 1, but was: %s.', config.fuzz_seconds) return False, False # Get fuzzer information. fuzzer_paths = utils.get_fuzz_targets(out_dir) if not fuzzer_paths: logging.error('No fuzzers were found in out directory: %s.', out_dir) return False, False # Run fuzzers for allotted time. total_num_fuzzers = len(fuzzer_paths) fuzzers_left_to_run = total_num_fuzzers min_seconds_per_fuzzer = config.fuzz_seconds // total_num_fuzzers for fuzzer_path in fuzzer_paths: run_seconds = max(config.fuzz_seconds // fuzzers_left_to_run, min_seconds_per_fuzzer) target = fuzz_target.FuzzTarget(fuzzer_path, run_seconds, out_dir, config.project_name, sanitizer=config.sanitizer) start_time = time.time() testcase, stacktrace = target.fuzz() config.fuzz_seconds -= (time.time() - start_time) if not testcase or not stacktrace: logging.info('Fuzzer %s, finished running.', target.target_name) else: utils.binary_print(b'Fuzzer %s, detected error:\n%s' % (target.target_name.encode(), stacktrace)) shutil.move(testcase, os.path.join(artifacts_dir, 'test_case')) stack_parser.parse_fuzzer_output(stacktrace, artifacts_dir) return True, True fuzzers_left_to_run -= 1 return True, False
def test_get_valid_project(self): """Tests that the latest build can be retrieved from GCS.""" test_target = fuzz_target.FuzzTarget('/example/path', 10, '/example/outdir', 'example') latest_build = test_target.get_lastest_build_version() self.assertIsNotNone(latest_build) self.assertTrue(latest_build.endswith('.zip')) self.assertTrue('address' in latest_build)
def test_get_valid_project(self): """Tests the latest build can be retrieved from GCS.""" with tempfile.TemporaryDirectory() as tmp_dir: test_target = fuzz_target.FuzzTarget('/example/do_stuff_fuzzer', 10, tmp_dir, 'example') oss_fuzz_build_path = test_target.download_oss_fuzz_build() self.assertIsNotNone(oss_fuzz_build_path) self.assertTrue(os.listdir(oss_fuzz_build_path))
def setUp(self): """Sets up example fuzz target to test is_reproducible method.""" self.fuzz_target_path = '/example/path' self.testcase_path = '/testcase' deployment = _create_deployment() self.test_target = fuzz_target.FuzzTarget( self.fuzz_target_path, fuzz_target.REPRODUCE_ATTEMPTS, '/example/outdir', deployment, deployment.config)
def setUp(self): """Sets up example fuzz target to test is_reproducible method.""" self.setUpPyfakefs() deployment = _create_deployment() config = deployment.config workspace = deployment.workspace self.fuzz_target = fuzz_target.FuzzTarget('/path/fuzz-target', 10, workspace, deployment, config)
def run_fuzzers(fuzz_seconds, workspace, project_name): """Runs all fuzzers for a specific OSS-Fuzz project. Args: fuzz_seconds: The total time allotted for fuzzing. workspace: The location in a shared volume to store a git repo and build artifacts. project_name: The name of the relevant OSS-Fuzz project. Returns: (True if run was successful, True if bug was found). """ # Validate inputs. if not os.path.exists(workspace): logging.error('Invalid workspace: %s.', workspace) return False, False out_dir = os.path.join(workspace, 'out') artifacts_dir = os.path.join(out_dir, 'artifacts') os.makedirs(artifacts_dir, exist_ok=True) if not fuzz_seconds or fuzz_seconds < 1: logging.error( 'Fuzz_seconds argument must be greater than 1, but was: %s.', format(fuzz_seconds)) return False, False # Get fuzzer information. fuzzer_paths = utils.get_fuzz_targets(out_dir) if not fuzzer_paths: logging.error('No fuzzers were found in out directory: %s.', format(out_dir)) return False, False # Run fuzzers for alotted time. total_num_fuzzers = len(fuzzer_paths) fuzzers_left_to_run = total_num_fuzzers min_seconds_per_fuzzer = fuzz_seconds // total_num_fuzzers for fuzzer_path in fuzzer_paths: run_seconds = max(fuzz_seconds // fuzzers_left_to_run, min_seconds_per_fuzzer) target = fuzz_target.FuzzTarget(fuzzer_path, run_seconds, out_dir, project_name) start_time = time.time() test_case, stack_trace = target.fuzz() fuzz_seconds -= (time.time() - start_time) if not test_case or not stack_trace: logging.info('Fuzzer %s, finished running.', target.target_name) else: logging.info('Fuzzer %s, detected error: %s.', target.target_name, stack_trace) shutil.move(test_case, os.path.join(artifacts_dir, 'test_case')) parse_fuzzer_output(stack_trace, artifacts_dir) return True, True fuzzers_left_to_run -= 1 return True, False
def setUp(self): """Sets up example fuzz target to test is_reproducible method.""" self.fuzz_target_name = 'fuzz-target' deployment = _create_deployment() self.workspace = deployment.workspace self.fuzz_target_path = os.path.join(self.workspace.out, self.fuzz_target_name) self.testcase_path = '/testcase' self.test_target = fuzz_target.FuzzTarget(self.fuzz_target_path, fuzz_target.REPRODUCE_ATTEMPTS, self.workspace, deployment, deployment.config)
def setUp(self): """Sets up dummy fuzz target to test is_crash_reportable method.""" self.fuzz_target_path = '/example/do_stuff_fuzzer' self.test_target = fuzz_target.FuzzTarget(self.fuzz_target_path, 100, '/example/outdir', 'example') self.oss_fuzz_build_path = '/oss-fuzz-build' self.setUpPyfakefs() self.fs.create_file(self.fuzz_target_path) self.oss_fuzz_target_path = os.path.join( self.oss_fuzz_build_path, os.path.basename(self.fuzz_target_path)) self.fs.create_file(self.oss_fuzz_target_path) self.testcase_path = '/testcase' self.fs.create_file(self.testcase_path, contents='')
def test_single_download(self): """Tests that the build directory was only downloaded once.""" with tempfile.TemporaryDirectory() as tmp_dir: test_target = fuzz_target.FuzzTarget('/example/do_stuff_fuzzer', 10, tmp_dir, 'example') latest_version = test_target.get_lastest_build_version() with unittest.mock.patch( 'fuzz_target.FuzzTarget.get_lastest_build_version', return_value=latest_version) as mocked_get_latest_build_version: for _ in range(5): oss_fuzz_build_path = test_target.download_oss_fuzz_build() self.assertEqual(1, mocked_get_latest_build_version.call_count) self.assertIsNotNone(oss_fuzz_build_path) self.assertTrue(os.listdir(oss_fuzz_build_path))
def setUp(self): """Sets up example fuzz target to test is_crash_reportable method.""" self.setUpPyfakefs() self.fuzz_target_path = '/example/do_stuff_fuzzer' deployment = _create_deployment() self.target = fuzz_target.FuzzTarget(self.fuzz_target_path, 100, deployment.workspace, deployment, deployment.config) self.oss_fuzz_build_path = '/oss-fuzz-build' self.fs.create_file(self.fuzz_target_path) self.oss_fuzz_target_path = os.path.join( self.oss_fuzz_build_path, os.path.basename(self.fuzz_target_path)) self.fs.create_file(self.oss_fuzz_target_path) self.testcase_path = '/testcase' self.fs.create_file(self.testcase_path, contents='') # Do this to prevent pyfakefs from messing with requests. self.fs.add_real_directory(os.path.dirname(certifi.__file__))
def test_download_valid_projects_corpus(self): """Tests that a vaild fuzz target returns a corpus directory.""" with tempfile.TemporaryDirectory() as tmp_dir: test_target = fuzz_target.FuzzTarget('testfuzzer', 3, 'test_out') test_target.project_name = EXAMPLE_PROJECT test_target.target_name = EXAMPLE_FUZZER test_target.out_dir = tmp_dir with unittest.mock.patch( 'fuzz_target.download_and_unpack_zip', return_value=tmp_dir) as mocked_download_and_unpack_zip: test_target.download_latest_corpus() (url, out_dir), _ = mocked_download_and_unpack_zip.call_args self.assertEqual( url, 'https://storage.googleapis.com/example-backup.' 'clusterfuzz-external.appspot.com/corpus/libFuzzer/' 'example_crash_fuzzer/public.zip') self.assertEqual(out_dir, os.path.join(tmp_dir, 'backup_corpus', EXAMPLE_FUZZER))
def run_fuzzers(project_name, fuzz_seconds, workspace): """Runs all fuzzers for a specific OSS-Fuzz project. Args: project_name: The name of the OSS-Fuzz project being built. fuzz_seconds: The total time allotted for fuzzing. workspace: The location in a shared volume to store a git repo and build artifacts. Returns: (True if run was successful, True if bug was found). """ # Validate inputs. if not os.path.exists(workspace): logging.error('Invalid workspace: %s.', workspace) return False, False out_dir = os.path.join(workspace, 'out') if not fuzz_seconds or fuzz_seconds < 1: logging.error( 'Fuzz_seconds argument must be greater than 1, but was: %s.', format(fuzz_seconds)) return False, False # Get fuzzer information. fuzzer_paths = utils.get_fuzz_targets(out_dir) if not fuzzer_paths: logging.error('No fuzzers were found in out directory: %s.', format(out_dir)) return False, False fuzz_seconds_per_target = fuzz_seconds // len(fuzzer_paths) # Run fuzzers for alotted time. for fuzzer_path in fuzzer_paths: target = fuzz_target.FuzzTarget(project_name, fuzzer_path, fuzz_seconds_per_target, out_dir) test_case, stack_trace = target.fuzz() if not test_case or not stack_trace: logging.info('Fuzzer %s, finished running.', target.target_name) else: logging.info('Fuzzer %s, detected error: %s.', target.target_name, stack_trace) shutil.move(test_case, os.path.join(out_dir, 'testcase')) return True, True return True, False
def setUp(self): """Sets up example fuzz target to test is_reproducible method.""" self.fuzz_target_name = 'fuzz-target' deployment = _create_deployment() self.config = deployment.config self.workspace = deployment.workspace self.fuzz_target_path = os.path.join(self.workspace.out, self.fuzz_target_name) self.setUpPyfakefs() self.fs.create_file(self.fuzz_target_path) self.testcase_path = '/testcase' self.fs.create_file(self.testcase_path) self.target = fuzz_target.FuzzTarget(self.fuzz_target_path, fuzz_target.REPRODUCE_ATTEMPTS, self.workspace, deployment, deployment.config) test_helpers.patch_environ(self, empty=True)
def test_timeout_reported(self, report_timeouts, expect_crash): """Tests that timeouts are not reported.""" with test_helpers.temp_dir_copy(TEST_DATA_PATH) as temp_dir: fuzz_target_path = os.path.join(temp_dir, 'build-out', self.TIMEOUT_FUZZER_NAME) shutil.copy(os.path.join(temp_dir, self.TIMEOUT_FUZZER_NAME), fuzz_target_path) deployment = _create_deployment(workspace=temp_dir, report_timeouts=report_timeouts) config = deployment.config fuzz_target_obj = fuzz_target.FuzzTarget( fuzz_target_path, fuzz_target.REPRODUCE_ATTEMPTS, deployment.workspace, deployment, config) with mock.patch('clusterfuzz._internal.bot.fuzzers.libfuzzer.' 'fix_timeout_argument_for_reproduction') as _: with mock.patch( 'clusterfuzz._internal.bot.fuzzers.libFuzzer.fuzzer.get_arguments', return_value=['-timeout=1', '-rss_limit_mb=2560']): fuzz_result = fuzz_target_obj.fuzz() self.assertEqual(bool(fuzz_result.testcase), expect_crash)
def test_invalid_build_dir(self): """Tests the download returns None when out_dir doesn't exist.""" test_target = fuzz_target.FuzzTarget('/example/do_stuff_fuzzer', 10, 'not/a/dir', 'example') self.assertIsNone(test_target.download_oss_fuzz_build())
def create_fuzz_target_obj(self, target_path, run_seconds): """Returns a fuzz target object.""" return fuzz_target.FuzzTarget(target_path, run_seconds, self.out_dir, self.clusterfuzz_deployment, self.config)
def setUp(self): """Sets up dummy fuzz target to test is_reproducible method.""" self.test_target = fuzz_target.FuzzTarget('/example/do_stuff_fuzzer', 100, '/example/outdir', 'example')
def setUp(self): """Sets up dummy fuzz target to test get_test_case method.""" self.test_target = fuzz_target.FuzzTarget('/example/path', 10, '/example/outdir')