def setUp(self): self.project_name = 'project' self.internal_project = helper.Project(self.project_name) self.external_project_path = os.path.join('/path', 'to', self.project_name) self.external_project = helper.Project(self.external_project_path, is_external=True) self.setUpPyfakefs()
def test_generate_swift_project(self, _): """Tests that the swift project uses the correct base image.""" helper._generate_impl(helper.Project(self.PROJECT_NAME), 'swift') self._verify_templated_files( templates.TEMPLATES, os.path.join(helper.OSS_FUZZ_DIR, 'projects', self.PROJECT_NAME), 'swift')
def _check_for_crash(project_name, fuzz_target, testcase_path): """Check for crash.""" def docker_run(args): command = ['docker', 'run', '--rm', '--privileged'] if sys.stdin.isatty(): command.append('-i') return utils.execute(command + args) logging.info('Checking for crash') out, err, return_code = helper.reproduce_impl( project=helper.Project(project_name), fuzzer_name=fuzz_target, valgrind=False, env_to_add=[], fuzzer_args=[], testcase_path=testcase_path, run_function=docker_run, err_result=(None, None, None)) if return_code is None: return None logging.info('stdout =\n%s', out) logging.info('stderr =\n%s', err) # pylint: disable=unsupported-membership-test has_start_marker = any(marker in out or marker in err for marker in START_MARKERS) has_end_marker = any(marker in out or marker in err for marker in END_MARKERS) if not has_start_marker or not has_end_marker: return None return _get_dedup_token(out + err)
def test_generate_oss_fuzz_project(self, _): """Tests that the correct files are generated for an OSS-Fuzz project.""" helper._generate_impl(helper.Project(self.PROJECT_NAME), self.PROJECT_LANGUAGE) self._verify_templated_files( templates.TEMPLATES, os.path.join(helper.OSS_FUZZ_DIR, 'projects', self.PROJECT_NAME), self.PROJECT_LANGUAGE)
def test_generate_external_project(self): """Tests that the correct files are generated for a non-OSS-Fuzz project.""" build_integration_path = '/newfakeproject/build-integration' helper._generate_impl( helper.Project('/newfakeproject/', is_external=True, build_integration_path=build_integration_path)) self._verify_templated_files(templates.EXTERNAL_TEMPLATES, build_integration_path)
def test_oss_fuzz_project(self, mock_docker_build): """Tests that build_image_impl works as intended with an OSS-Fuzz project.""" project_name = 'example' self.assertTrue(helper.build_image_impl(helper.Project(project_name))) build_dir = os.path.join(helper.OSS_FUZZ_DIR, 'projects', project_name) mock_docker_build.assert_called_with([ '-t', 'gcr.io/oss-fuzz/example', '--file', os.path.join(build_dir, 'Dockerfile'), build_dir ])
def test_base_image(self, mock_docker_build): """Tests that build_image_impl works as intended with a base-image.""" image_name = 'base-image' self.assertTrue(helper.build_image_impl(helper.Project(image_name))) build_dir = os.path.join(helper.OSS_FUZZ_DIR, 'infra/base-images/base-image') mock_docker_build.assert_called_with([ '-t', 'gcr.io/oss-fuzz-base/base-image', '--file', os.path.join(build_dir, 'Dockerfile'), build_dir ])
def test_external_project(self, mock_docker_build): """Tests that build_image_impl works as intended with a non-OSS-Fuzz project.""" with tempfile.TemporaryDirectory() as temp_dir: project_src_path = os.path.join(temp_dir, 'example') os.mkdir(project_src_path) build_integration_path = 'build-integration' project = helper.Project(project_src_path, is_external=True, build_integration_path=build_integration_path) self.assertTrue(helper.build_image_impl(project)) mock_docker_build.assert_called_with([ '-t', 'gcr.io/oss-fuzz/example', '--file', os.path.join(project_src_path, build_integration_path, 'Dockerfile'), project_src_path ])
def test_build_fuzzers_from_commit(self): """Tests if the fuzzers can build at a specified commit. This is done by using a known regression range for a specific test case. The old commit should show the error when its fuzzers run and the new one should not. """ with tempfile.TemporaryDirectory() as tmp_dir: test_repo = test_repos.TEST_REPOS[1] self.assertTrue(helper.build_image_impl(test_repo.project_name)) host_src_dir = build_specified_commit.copy_src_from_docker( test_repo.project_name, tmp_dir) test_repo_manager = repo_manager.clone_repo_and_get_manager( test_repo.git_url, host_src_dir, test_repo.oss_repo_name) build_data = build_specified_commit.BuildData( sanitizer='address', architecture='x86_64', engine='libfuzzer', project_name=test_repo.project_name) build_specified_commit.build_fuzzers_from_commit( test_repo.old_commit, test_repo_manager, host_src_dir, build_data) project = helper.Project(test_repo.project_name) old_result = helper.reproduce_impl( project=project, fuzzer_name=test_repo.fuzz_target, valgrind=False, env_to_add=[], fuzzer_args=[], testcase_path=test_repo.testcase_path) build_specified_commit.build_fuzzers_from_commit( test_repo.project_name, test_repo_manager, host_src_dir, build_data) new_result = helper.reproduce_impl( project=project, fuzzer_name=test_repo.fuzz_target, valgrind=False, env_to_add=[], fuzzer_args=[], testcase_path=test_repo.testcase_path) self.assertNotEqual(new_result, old_result)
def test_pull(self, mock_pull_images, _): """Tests that pull=True is handled properly.""" image_name = 'base-image' project = helper.Project(image_name, is_external=True) self.assertTrue(helper.build_image_impl(project, pull=True)) mock_pull_images.assert_called_with('c++')
def test_no_cache(self, mock_docker_build): """Tests that cache=False is handled properly.""" image_name = 'base-image' helper.build_image_impl(helper.Project(image_name), cache=False) self.assertIn('--no-cache', mock_docker_build.call_args_list[0][0][0])
def build_fuzzers_from_commit(commit, build_repo_manager, host_src_path, build_data, base_builder_repo=None): """Builds a OSS-Fuzz fuzzer at a specific commit SHA. Args: commit: The commit SHA to build the fuzzers at. build_repo_manager: The OSS-Fuzz project's repo manager to be built at. build_data: A struct containing project build information. base_builder_repo: A BaseBuilderRepo. Returns: 0 on successful build or error code on failure. """ oss_fuzz_repo_manager = repo_manager.RepoManager(helper.OSS_FUZZ_DIR) num_retry = 1 def cleanup(): # Re-copy /src for a clean checkout every time. copy_src_from_docker(build_data.project_name, os.path.dirname(host_src_path)) build_repo_manager.fetch_all_remotes() projects_dir = os.path.join('projects', build_data.project_name) dockerfile_path = os.path.join(projects_dir, 'Dockerfile') for i in range(num_retry + 1): build_repo_manager.checkout_commit(commit, clean=False) post_checkout_steps = get_required_post_checkout_steps(dockerfile_path) for workdir, post_checkout_step in post_checkout_steps: logging.info('Running post-checkout step `%s` in %s.', post_checkout_step, workdir) helper.docker_run([ '-w', workdir, '-v', host_src_path + ':' + '/src', 'gcr.io/oss-fuzz/' + build_data.project_name, '/bin/bash', '-c', post_checkout_step, ]) project = helper.Project(build_data.project_name) result = helper.build_fuzzers_impl( project=project, clean=True, engine=build_data.engine, sanitizer=build_data.sanitizer, architecture=build_data.architecture, env_to_add=None, source_path=host_src_path, mount_path='/src') if result or i == num_retry: break # Retry with an OSS-Fuzz builder container that's closer to the project # commit date. commit_date = build_repo_manager.commit_date(commit) # Find first change in the projects/<PROJECT> directory before the project # commit date. oss_fuzz_commit, _, _ = oss_fuzz_repo_manager.git([ 'log', '--before=' + commit_date.isoformat(), '-n1', '--format=%H', projects_dir ], check_result=True) oss_fuzz_commit = oss_fuzz_commit.strip() if not oss_fuzz_commit: logging.info( 'Could not find first OSS-Fuzz commit prior to upstream commit. ' 'Falling back to oldest integration commit.') # Find the oldest commit. oss_fuzz_commit, _, _ = oss_fuzz_repo_manager.git( ['log', '--reverse', '--format=%H', projects_dir], check_result=True) oss_fuzz_commit = oss_fuzz_commit.splitlines()[0].strip() if not oss_fuzz_commit: logging.error('Failed to get oldest integration commit.') break logging.info('Build failed. Retrying on earlier OSS-Fuzz commit %s.', oss_fuzz_commit) # Check out projects/<PROJECT> dir to the commit that was found. oss_fuzz_repo_manager.git(['checkout', oss_fuzz_commit, projects_dir], check_result=True) # Also use the closest base-builder we can find. if base_builder_repo: base_builder_digest = base_builder_repo.find_digest(commit_date) if not base_builder_digest: return False logging.info('Using base-builder with digest %s.', base_builder_digest) _replace_base_builder_digest(dockerfile_path, base_builder_digest) # Rebuild image and re-copy src dir since things in /src could have changed. if not _build_image_with_retries(build_data.project_name): logging.error('Failed to rebuild image.') return False cleanup() cleanup() return result
def _build_image_with_retries(project_name): """Build image with retries.""" return helper.build_image_impl(helper.Project(project_name))
def test_pull(self, mock_pull_images, _): """Tests that pull=True is handled properly.""" image_name = 'base-image' self.assertTrue( helper.build_image_impl(helper.Project(image_name), pull=True)) mock_pull_images.assert_called_with()