示例#1
0
 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()
示例#2
0
 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')
示例#3
0
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)
示例#4
0
 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)
示例#5
0
 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)
示例#6
0
 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
   ])
示例#7
0
 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
   ])
示例#8
0
 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
     ])
示例#9
0
    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)
示例#10
0
 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++')
示例#11
0
 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])
示例#12
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
示例#13
0
def _build_image_with_retries(project_name):
    """Build image with retries."""
    return helper.build_image_impl(helper.Project(project_name))
示例#14
0
 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()