diff options
-rw-r--r-- | infra/bisector.py | 26 | ||||
-rw-r--r-- | infra/build_specified_commit.py | 25 | ||||
-rw-r--r-- | infra/build_specified_commit_test.py | 10 | ||||
-rwxr-xr-x | infra/helper.py | 14 | ||||
-rw-r--r-- | infra/repo_manager.py | 10 |
5 files changed, 60 insertions, 25 deletions
diff --git a/infra/bisector.py b/infra/bisector.py index 5eb1e776..fdb078b3 100644 --- a/infra/bisector.py +++ b/infra/bisector.py @@ -32,6 +32,7 @@ This is done with the following steps: import argparse import logging +import os import tempfile import build_specified_commit @@ -42,6 +43,7 @@ import utils def main(): """Finds the commit SHA where an error was initally introduced.""" + logging.getLogger().setLevel(logging.INFO) utils.chdir_to_root() parser = argparse.ArgumentParser( description='git bisection for finding introduction of bugs') @@ -90,7 +92,7 @@ def main(): return 0 -def bisect(old_commit, new_commit, test_case_path, fuzz_target, build_data): +def bisect(old_commit, new_commit, test_case_path, fuzz_target, build_data): # pylint: disable=too-many-locals """From a commit range, this function caluclates which introduced a specific error from a fuzz test_case_path. @@ -108,27 +110,33 @@ def bisect(old_commit, new_commit, test_case_path, fuzz_target, build_data): ValueError: when a repo url can't be determine from the project. """ with tempfile.TemporaryDirectory() as tmp_dir: - repo_url, repo_name = build_specified_commit.detect_main_repo( + repo_url, repo_path = build_specified_commit.detect_main_repo( build_data.project_name, commit=old_commit) - if not repo_url or not repo_name: + if not repo_url or not repo_path: raise ValueError('Main git repo can not be determined.') - bisect_repo_manager = repo_manager.RepoManager(repo_url, - tmp_dir, - repo_name=repo_name) + + host_src_dir = build_specified_commit.copy_src_from_docker( + build_data.project_name, tmp_dir) + + bisect_repo_manager = repo_manager.RepoManager( + repo_url, host_src_dir, repo_name=os.path.basename(repo_path)) commit_list = bisect_repo_manager.get_commit_list(old_commit, new_commit) old_idx = len(commit_list) - 1 new_idx = 0 + logging.info('Testing against new_commit (%s)', commit_list[new_idx]) build_specified_commit.build_fuzzers_from_commit(commit_list[new_idx], bisect_repo_manager, - build_data) + host_src_dir, build_data) expected_error_code = helper.reproduce_impl(build_data.project_name, fuzz_target, False, [], [], test_case_path) # Check if the error is persistent through the commit range + logging.info('Testing against old_commit (%s)', commit_list[old_idx]) build_specified_commit.build_fuzzers_from_commit( commit_list[old_idx], bisect_repo_manager, + host_src_dir, build_data, ) @@ -139,9 +147,11 @@ def bisect(old_commit, new_commit, test_case_path, fuzz_target, build_data): while old_idx - new_idx > 1: curr_idx = (old_idx + new_idx) // 2 + logging.info('Testing against %s (idx=%d)', commit_list[curr_idx], + curr_idx) build_specified_commit.build_fuzzers_from_commit(commit_list[curr_idx], bisect_repo_manager, - build_data) + host_src_dir, build_data) error_code = helper.reproduce_impl(build_data.project_name, fuzz_target, False, [], [], test_case_path) if expected_error_code == error_code: diff --git a/infra/build_specified_commit.py b/infra/build_specified_commit.py index 515dae24..f4134ab8 100644 --- a/infra/build_specified_commit.py +++ b/infra/build_specified_commit.py @@ -29,7 +29,25 @@ BuildData = collections.namedtuple( 'BuildData', ['project_name', 'engine', 'sanitizer', 'architecture']) -def build_fuzzers_from_commit(commit, build_repo_manager, build_data): +def copy_src_from_docker(project_name, host_dir): + """Copy /src from docker to the host.""" + # Copy /src to host. + image_name = 'gcr.io/oss-fuzz/' + project_name + docker_args = [ + '-v', + host_dir + ':/out', + image_name, + 'cp', + '-r', + '/src', + '/out', + ] + helper.docker_run(docker_args) + return os.path.join(host_dir, 'src') + + +def build_fuzzers_from_commit(commit, build_repo_manager, host_src_path, + build_data): """Builds a OSS-Fuzz fuzzer at a specific commit SHA. Args: @@ -46,9 +64,8 @@ def build_fuzzers_from_commit(commit, build_repo_manager, build_data): sanitizer=build_data.sanitizer, architecture=build_data.architecture, env_to_add=None, - source_path=build_repo_manager.repo_dir, - mount_location=os.path.join( - '/src', build_repo_manager.repo_name)) + source_path=host_src_path, + mount_location=os.path.join('/src')) def detect_main_repo(project_name, repo_name=None, commit=None): diff --git a/infra/build_specified_commit_test.py b/infra/build_specified_commit_test.py index 9fdaae47..6f666856 100644 --- a/infra/build_specified_commit_test.py +++ b/infra/build_specified_commit_test.py @@ -44,8 +44,12 @@ class BuildImageIntegrationTests(unittest.TestCase): with tempfile.TemporaryDirectory() as tmp_dir: test_case = test_repos.TEST_REPOS[0] + self.assertTrue(helper.build_image_impl(test_case.project_name)) + host_src_dir = build_specified_commit.copy_src_from_docker( + test_case.project_name, tmp_dir) + test_repo_manager = repo_manager.RepoManager( - test_case.git_url, tmp_dir, repo_name=test_case.oss_repo_name) + test_case.git_url, host_src_dir, repo_name=test_case.oss_repo_name) build_data = build_specified_commit.BuildData( sanitizer='address', architecture='x86_64', @@ -54,13 +58,13 @@ class BuildImageIntegrationTests(unittest.TestCase): build_specified_commit.build_fuzzers_from_commit(test_case.old_commit, test_repo_manager, - build_data) + host_src_dir, build_data) old_error_code = helper.reproduce_impl(test_case.project_name, test_case.fuzz_target, False, [], [], test_case.test_case_path) build_specified_commit.build_fuzzers_from_commit(test_case.new_commit, test_repo_manager, - build_data) + host_src_dir, build_data) new_error_code = helper.reproduce_impl(test_case.project_name, test_case.fuzz_target, False, [], [], test_case.test_case_path) diff --git a/infra/helper.py b/infra/helper.py index 1d512e13..844b7baa 100755 --- a/infra/helper.py +++ b/infra/helper.py @@ -498,18 +498,20 @@ def build_fuzzers_impl( # pylint: disable=too-many-arguments command = ['--cap-add', 'SYS_PTRACE'] + _env_to_docker_args(env) if source_path: workdir = _workdir_from_dockerfile(project_name) - if workdir == '/src': - print('Cannot use local checkout with "WORKDIR: /src".', file=sys.stderr) - return 1 - if not mount_location: + if mount_location: command += [ '-v', - '%s:%s' % (_get_absolute_path(source_path), workdir), + '%s:%s' % (_get_absolute_path(source_path), mount_location), ] else: + if workdir == '/src': + print('Cannot use local checkout with "WORKDIR: /src".', + file=sys.stderr) + return 1 + command += [ '-v', - '%s:%s' % (_get_absolute_path(source_path), mount_location), + '%s:%s' % (_get_absolute_path(source_path), workdir), ] command += [ diff --git a/infra/repo_manager.py b/infra/repo_manager.py index a6789fb0..d240ae1f 100644 --- a/infra/repo_manager.py +++ b/infra/repo_manager.py @@ -53,7 +53,9 @@ class RepoManager: else: self.repo_name = os.path.basename(self.repo_url).replace('.git', '') self.repo_dir = os.path.join(self.base_dir, self.repo_name) - self._clone() + + if not os.path.exists(self.repo_dir): + self._clone() def _clone(self): """Creates a clone of the repo in the specified directory. @@ -136,7 +138,7 @@ class RepoManager: ValueError: When either the old or new commit does not exist. RuntimeError: When there is an error getting the commit list. """ - + self.fetch_unshallow() if not self.commit_exists(old_commit): raise ValueError('The old commit %s does not exist' % old_commit) if not self.commit_exists(new_commit): @@ -157,8 +159,8 @@ class RepoManager: def fetch_unshallow(self): """Gets the current git repository history.""" - git_path = os.path.join(self.repo_dir, '.git', 'shallow') - if os.path.exists(git_path): + shallow_file = os.path.join(self.repo_dir, '.git', 'shallow') + if os.path.exists(shallow_file): utils.execute(['git', 'fetch', '--unshallow'], self.repo_dir, check_result=True) |