Example #1
0
def handle_timeout(subscriber, subscription, ack_id, oss_fuzz_dir, message):
  """Handle a timeout."""
  subscriber.acknowledge(subscription=subscription, ack_ids=[ack_id])

  bisect_type = message.attributes['type']
  source_id = get_source_id(message)

  logging.error('Task %s timed out (source_id=%s)', bisect_type, source_id)

  if bisect_type not in ('fixed', 'regressed'):
    return

  old_commit = message.attributes['old_commit']
  new_commit = message.attributes['new_commit']

  if bisect_type == 'fixed':
    entity = osv.FixResult(id=source_id)
  else:
    assert bisect_type == 'regressed'
    entity = osv.RegressResult(id=source_id)

  _set_result_attributes(oss_fuzz_dir, message, entity)

  entity.commit = format_commit_range(old_commit, new_commit)
  entity.error = 'Timeout'
  entity.put()
Example #2
0
def process_bisect_task(oss_fuzz_dir, bisect_type, source_id, message):
    """Process a bisect task."""
    bisect_type = message.attributes['type']
    project_name = message.attributes['project_name']
    engine = 'libfuzzer'
    architecture = message.attributes['architecture'] or 'x86_64'
    sanitizer = message.attributes['sanitizer']
    fuzz_target = message.attributes['fuzz_target']
    old_commit = message.attributes['old_commit']

    new_commit = message.attributes['new_commit']
    testcase = message.data
    logging.info(
        'Performing %s bisect on source_id=%s, project=%s, engine=%s, '
        'architecture=%s, sanitizer=%s, fuzz_target=%s, old_commit=%s, '
        'new_commit=%s', bisect_type, source_id, project_name, engine,
        architecture, sanitizer, fuzz_target, old_commit, new_commit)

    result = None
    if project_name in PROJECT_DENYLIST:
        logging.info('Skipping bisect for denylisted project %s', project_name)
    elif not old_commit:
        logging.info('Skipping bisect since there is no old_commit.')
    else:
        result = do_bisect(bisect_type, source_id, project_name, engine,
                           sanitizer, architecture, fuzz_target, old_commit,
                           new_commit, testcase)

    if result.repo_url in REPO_DENYLIST:
        logging.info('Skipping because of denylisted repo %s.',
                     result.repo_url)
        return

    if bisect_type == 'fixed':
        entity = osv.FixResult(id=source_id)
    else:
        assert bisect_type == 'regressed'
        entity = osv.RegressResult(id=source_id)

    _set_result_attributes(oss_fuzz_dir, message, entity)

    if result and result.commit:
        logging.info('Bisected to %s', result.commit)
        entity.commit = result.commit
        entity.repo_url = result.repo_url
    else:
        logging.info(
            'Bisect not successfully performed. Setting commit range from request.'
        )
        entity.commit = format_commit_range(old_commit, new_commit)
        entity.repo_url = result.repo_url if result else None
        entity.error = 'Bisect error'

    entity.put()
Example #3
0
    def test_fixed_range_too_long(self):
        """Test fixed range that's too long."""
        message = mock.Mock()
        message.attributes = {
            'source_id': 'oss-fuzz:123',
            'allocated_id': 'OSV-2020-1337',
        }

        regress_result = osv.RegressResult(
            id='oss-fuzz:123',
            commit='eefe8ec3f1f90d0e684890e810f3f21e8500a4cd',
            repo_url='https://repo.com/repo',
            issue_id='9001',
            project='project',
            ecosystem='ecosystem',
            summary='Heap-buffer-overflow in Foo',
            severity='MEDIUM',
            reference_urls=['https://url/'])
        regress_result.put()

        fix_result = osv.FixResult(
            id='oss-fuzz:123',
            commit=('eefe8ec3f1f90d0e684890e810f3f21e8500a4cd:'
                    'b587c21c36a84e16cfc6b39eb68578d43b5281ad'),
            repo_url='https://repo.com/repo',
            project='project',
            ecosystem='ecosystem',
            summary='Heap-buffer-overflow in Foo',
            details='DETAILS',
            severity='MEDIUM',
            reference_urls=['https://url/'])
        fix_result.put()

        oss_fuzz.process_impact_task('oss-fuzz:123', message)
        self.expect_dict_equal(
            'fixed_range_too_long',
            ndb.Key(osv.Bug, 'OSV-2020-1337').get()._to_dict())

        affected_commits = list(osv.AffectedCommit.query())

        self.assertCountEqual([
            'b9b3fd4732695b83c3068b7b6a14bb372ec31f98',
            'ff8cc32ba60ad9cbb3b23f0a82aad96ebe9ff76b',
            'febfac1940086bc1f6d3dc33fda0a1d1ba336209',
            '4c155795426727ea05575bd5904321def23c03f4',
            'b1c95a196f22d06fcf80df8c6691cd113d8fefff',
            'eefe8ec3f1f90d0e684890e810f3f21e8500a4cd',
            '8d8242f545e9cec3e6d0d2e3f5bde8be1c659735',
            '3ea6feea9bb853596c727abab309476cc07d1505',
            '36f0bd9549298b44f9ff2496c9dd1326b3a9d0e2',
        ], [commit.commit for commit in affected_commits])
Example #4
0
def handle_timeout(task_type, source_id, oss_fuzz_dir, message):
  """Handle a timeout."""
  old_commit = message.attributes['old_commit']
  new_commit = message.attributes['new_commit']

  if task_type == 'fixed':
    entity = osv.FixResult(id=source_id)
  else:
    assert task_type == 'regressed'
    entity = osv.RegressResult(id=source_id)

  _set_result_attributes(oss_fuzz_dir, message, entity)

  entity.commit = format_commit_range(old_commit, new_commit)
  entity.error = 'Timeout'
  entity.put()
Example #5
0
    def test_zero_regression_range(self):
        """Test regression range with "0:X"."""
        message = mock.Mock()
        message.attributes = {
            'source_id': 'oss-fuzz:123',
            'allocated_id': 'OSV-2020-1337',
        }

        regress_result = osv.RegressResult(
            id='oss-fuzz:123',
            commit='unknown:eefe8ec3f1f90d0e684890e810f3f21e8500a4cd',
            repo_url='https://repo.com/repo',
            issue_id='9001',
            project='project',
            ecosystem='ecosystem',
            summary='Heap-buffer-overflow in Foo',
            severity='MEDIUM',
            reference_urls=['https://url/'])
        regress_result.put()

        fix_result = osv.FixResult(
            id='oss-fuzz:123',
            commit='8d8242f545e9cec3e6d0d2e3f5bde8be1c659735',
            repo_url='https://repo.com/repo',
            project='project',
            ecosystem='ecosystem',
            summary='Heap-buffer-overflow in Foo',
            details='DETAILS',
            severity='MEDIUM',
            reference_urls=['https://url/'])
        fix_result.put()

        oss_fuzz.process_impact_task('oss-fuzz:123', message)
        self.expect_dict_equal(
            'zero_regression_range',
            ndb.Key(osv.Bug, 'OSV-2020-1337').get()._to_dict())

        affected_commits = list(osv.AffectedCommit.query())

        self.assertCountEqual([
            'ff8cc32ba60ad9cbb3b23f0a82aad96ebe9ff76b',
            'febfac1940086bc1f6d3dc33fda0a1d1ba336209',
            '4c155795426727ea05575bd5904321def23c03f4',
            'b1c95a196f22d06fcf80df8c6691cd113d8fefff',
            'eefe8ec3f1f90d0e684890e810f3f21e8500a4cd',
        ], [commit.commit for commit in affected_commits])
Example #6
0
    def test_update_add_fix(self):
        """Test basic update adding a fix."""
        fix_result = osv.FixResult(
            id='source:BLAH-124.yaml',
            commit='8d8242f545e9cec3e6d0d2e3f5bde8be1c659735')
        fix_result.put()
        task_runner = worker.TaskRunner(ndb_client, None, self.tmp_dir.name,
                                        None, None)
        message = mock.Mock()
        message.attributes = {
            'source':
            'source',
            'path':
            'BLAH-124.yaml',
            'original_sha256': ('5d6224b81fb100d51bf61c2568b1c75f'
                                '1df355ace1872af1b7eb0b1b5d93f477'),
            'deleted':
            'false',
        }
        task_runner._source_update(message)

        repo = pygit2.Repository(self.remote_source_repo_path)
        commit = repo.head.peel()

        self.assertEqual('*****@*****.**', commit.author.email)
        self.assertEqual('OSV', commit.author.name)
        self.assertEqual('Update BLAH-124', commit.message)
        diff = repo.diff(commit.parents[0], commit)

        self.expect_equal('diff_update_add_fix', diff.patch)
        self.expect_dict_equal('update_add_fix',
                               osv.Bug.get_by_id('BLAH-124')._to_dict())

        affected_commits = list(osv.AffectedCommit.query())
        self.assertCountEqual([
            '4c155795426727ea05575bd5904321def23c03f4',
            'b1c95a196f22d06fcf80df8c6691cd113d8fefff',
            'eefe8ec3f1f90d0e684890e810f3f21e8500a4cd',
            'febfac1940086bc1f6d3dc33fda0a1d1ba336209',
            'ff8cc32ba60ad9cbb3b23f0a82aad96ebe9ff76b',
        ], [commit.commit for commit in affected_commits])
Example #7
0
    def test_simplify_range(self):
        """Test simplifying commit range."""
        message = mock.Mock()
        message.attributes = {
            'source_id': 'oss-fuzz:123',
            'allocated_id': 'OSV-2020-1337',
        }

        regress_result = osv.RegressResult(
            id='oss-fuzz:123',
            commit=('a2ba949290915d445d34d0e8e9de2e7ce38198fc:'
                    'eefe8ec3f1f90d0e684890e810f3f21e8500a4cd'),
            repo_url='https://repo.com/repo',
            issue_id='9001',
            project='project',
            ecosystem='ecosystem',
            summary='Heap-buffer-overflow in Foo',
            severity='MEDIUM',
            reference_urls=['https://url/'])
        regress_result.put()

        fix_result = osv.FixResult(
            id='oss-fuzz:123',
            commit=('b1c95a196f22d06fcf80df8c6691cd113d8fefff:'
                    '8d8242f545e9cec3e6d0d2e3f5bde8be1c659735'),
            repo_url='https://repo.com/repo',
            project='project',
            ecosystem='ecosystem',
            summary='Heap-buffer-overflow in Foo',
            details='DETAILS',
            severity='MEDIUM',
            reference_urls=['https://url/'])
        fix_result.put()

        oss_fuzz.process_impact_task('oss-fuzz:123', message)
        self.expect_dict_equal(
            'simplify_range',
            ndb.Key(osv.Bug, 'OSV-2020-1337').get()._to_dict())
Example #8
0
def process_impact_task(source_id, message):
  """Process an impact task."""
  logging.info('Processing impact task for %s', source_id)

  regress_result = ndb.Key(osv.RegressResult, source_id).get()
  if not regress_result:
    logging.error('Missing RegressResult for %s', source_id)
    return

  fix_result = ndb.Key(osv.FixResult, source_id).get()
  if not fix_result:
    logging.warning('Missing FixResult for %s', source_id)
    fix_result = osv.FixResult()

  # Check if there is an existing Bug for the same source, but with a different
  # allocated ID. This shouldn't happen.
  allocated_bug_id = message.attributes['allocated_id']

  existing_bug = osv.Bug.query(osv.Bug.source_id == source_id).get()
  if existing_bug and existing_bug.key.id() != allocated_bug_id:
    logging.error('Bug entry already exists for %s with a different ID %s',
                  source_id, existing_bug.key.id())
    return

  if existing_bug and existing_bug.status == osv.BugStatus.INVALID:
    logging.warning('Bug %s already marked as invalid.', existing_bug.key.id())
    return

  if existing_bug:
    public = existing_bug.public
  else:
    raise osv.ImpactError('Task requested without Bug allocated.')

  # TODO(ochang): Handle changing repo types? e.g. SVN -> Git.

  repo_url = regress_result.repo_url or fix_result.repo_url
  if not repo_url:
    raise osv.ImpactError('No repo_url set')

  issue_id = fix_result.issue_id or regress_result.issue_id
  fix_commit = fix_result.commit

  with tempfile.TemporaryDirectory() as tmp_dir:
    repo = osv.clone_with_retries(repo_url, tmp_dir)

    # If not a precise fix commit, try to find the exact one by going through
    # commit messages (oss-fuzz only).
    if source_id.startswith(SOURCE_PREFIX) and ':' in fix_commit:
      start_commit, end_commit = fix_commit.split(':')
      commit = find_oss_fuzz_fix_via_commit(repo, start_commit, end_commit,
                                            source_id, issue_id)
      if commit:
        logging.info('Found exact fix commit %s via commit message (oss-fuzz)',
                     commit)
        fix_commit = commit

    # Actually compute the affected commits/tags.
    result = osv.get_affected(repo, regress_result.commit, fix_commit)
    logging.info('Found affected %s', ', '.join(result.tags))

  # If the range resolved to a single commit, simplify it.
  if len(result.fix_commits) == 1:
    fix_commit = result.fix_commits[0]
  elif not result.fix_commits:
    # Not fixed.
    fix_commit = ''

  if len(result.regress_commits) == 1:
    regress_commit = result.regress_commits[0]
  else:
    regress_commit = regress_result.commit

  project = fix_result.project or regress_result.project
  ecosystem = fix_result.ecosystem or regress_result.ecosystem
  summary = fix_result.summary or regress_result.summary
  details = fix_result.details or regress_result.details
  severity = fix_result.severity or regress_result.severity
  reference_urls = fix_result.reference_urls or regress_result.reference_urls

  update_affected_commits(allocated_bug_id, result, project, ecosystem, public)

  existing_bug.repo_url = repo_url
  existing_bug.fixed = fix_commit
  existing_bug.regressed = regress_commit
  existing_bug.affected = result.tags
  existing_bug.affected_fuzzy = osv.normalize_tags(result.tags)
  existing_bug.confidence = result.confidence
  existing_bug.issue_id = issue_id
  existing_bug.project = project
  existing_bug.ecosystem = ecosystem
  existing_bug.summary = summary
  existing_bug.details = details
  existing_bug.status = osv.BugStatus.PROCESSED
  existing_bug.severity = severity
  existing_bug.reference_urls = reference_urls

  existing_bug.additional_commit_ranges = []
  # Don't display additional ranges for imprecise commits, as they can be
  # confusing.
  if ':' in existing_bug.fixed or ':' in existing_bug.regressed:
    existing_bug.put()
    return

  def _sort_key(value):
    # Allow sorting of None values.
    return (value[0] or '', value[1] or '')

  for introduced_in, fixed_in in sorted(result.affected_ranges, key=_sort_key):
    if (introduced_in == existing_bug.regressed and
        (fixed_in or '') == existing_bug.fixed):
      # Don't include the main range.
      continue

    existing_bug.additional_commit_ranges.append(
        osv.CommitRange(introduced_in=introduced_in, fixed_in=fixed_in))

  existing_bug.put()
Example #9
0
def process_impact_task(source_id, message):
    """Process an impact task."""
    logging.info('Processing impact task for %s', source_id)

    regress_result = ndb.Key(osv.RegressResult, source_id).get()
    if not regress_result:
        logging.error('Missing RegressResult for %s', source_id)
        return

    fix_result = ndb.Key(osv.FixResult, source_id).get()
    if not fix_result:
        logging.warning('Missing FixResult for %s', source_id)
        fix_result = osv.FixResult()

    # Check if there is an existing Bug for the same source, but with a different
    # allocated ID. This shouldn't happen.
    allocated_bug_id = message.attributes['allocated_id']

    existing_bug = osv.Bug.query(osv.Bug.source_id == source_id).get()
    if existing_bug and existing_bug.key.id() != allocated_bug_id:
        logging.error('Bug entry already exists for %s with a different ID %s',
                      source_id, existing_bug.key.id())
        return

    if existing_bug and existing_bug.status == osv.BugStatus.INVALID:
        logging.warning('Bug %s already marked as invalid.',
                        existing_bug.key.id())
        return

    if existing_bug:
        public = existing_bug.public
    else:
        raise osv.ImpactError('Task requested without Bug allocated.')

    repo_url = regress_result.repo_url or fix_result.repo_url
    if not repo_url:
        raise osv.ImpactError('No repo_url set')

    # Always populate Bug attributes, even if the remainder of the analysis fails.
    # This does not mark the Bug as being valid.
    set_bug_attributes(existing_bug, regress_result, fix_result)
    existing_bug.put()

    issue_id = fix_result.issue_id or regress_result.issue_id
    fix_commit = fix_result.commit

    with tempfile.TemporaryDirectory() as tmp_dir:
        repo = osv.clone_with_retries(repo_url, tmp_dir)

        # If not a precise fix commit, try to find the exact one by going through
        # commit messages (oss-fuzz only).
        if source_id.startswith(SOURCE_PREFIX) and ':' in fix_commit:
            start_commit, end_commit = fix_commit.split(':')
            commit = find_oss_fuzz_fix_via_commit(repo, start_commit,
                                                  end_commit, source_id,
                                                  issue_id)
            if commit:
                logging.info(
                    'Found exact fix commit %s via commit message (oss-fuzz)',
                    commit)
                fix_commit = commit

        # Actually compute the affected commits/tags.
        repo_analyzer = osv.RepoAnalyzer()
        result = repo_analyzer.get_affected(repo, regress_result.commit,
                                            fix_commit)
        affected_tags = sorted(list(result.tags))
        logging.info('Found affected %s', ', '.join(affected_tags))

    # If the range resolved to a single commit, simplify it.
    if len(result.fix_commits) == 1:
        fix_commit = result.fix_commits[0]
    elif not result.fix_commits:
        # Not fixed.
        fix_commit = ''

    if (len(result.regress_commits) == 1
            and osv.UNKNOWN_COMMIT not in regress_result.commit):
        regress_commit = result.regress_commits[0]
    else:
        regress_commit = regress_result.commit

    project = fix_result.project or regress_result.project
    ecosystem = fix_result.ecosystem or regress_result.ecosystem
    osv.update_affected_commits(allocated_bug_id, result.commits, project,
                                ecosystem, public)

    affected_tags = sorted(list(result.tags))
    existing_bug.fixed = fix_commit
    existing_bug.regressed = regress_commit
    existing_bug.affected = affected_tags
    existing_bug.affected_fuzzy = osv.normalize_tags(affected_tags)
    existing_bug.status = osv.BugStatus.PROCESSED

    # For the AffectedRange, use the first commit in the regress commit range, and
    # the last commit in the fix commit range.
    introduced = result.regress_commits[0] if result.regress_commits else ''
    fixed = result.fix_commits[-1] if result.fix_commits else ''
    existing_bug.affected_ranges = [
        osv.AffectedRange(type='GIT',
                          repo_url=repo_url,
                          introduced=introduced,
                          fixed=fixed),
    ]

    # Expose range data in `database_specific`.
    database_specific = {}
    if ':' in existing_bug.regressed:
        database_specific['introduced_range'] = existing_bug.regressed
    if ':' in existing_bug.fixed:
        database_specific['fixed_range'] = existing_bug.fixed

    if database_specific:
        existing_bug.database_specific = database_specific

    # Don't display additional ranges for imprecise commits, as they can be
    # confusing.
    if ':' in existing_bug.fixed or ':' in existing_bug.regressed:
        existing_bug.put()
        return

    def _sort_key(value):
        # Allow sorting of None values.
        return (value[0] or '', value[1] or '')

    for introduced_in, fixed_in in sorted(result.affected_ranges,
                                          key=_sort_key):
        if not fixed_in:
            fixed_in = ''

        if (introduced_in == existing_bug.regressed
                and fixed_in == existing_bug.fixed):
            # Don't repeat the main range.
            continue

        existing_bug.affected_ranges.append(
            osv.AffectedRange(type='GIT',
                              repo_url=repo_url,
                              introduced=introduced_in,
                              fixed=fixed_in))

    existing_bug.put()
Example #10
0
    def test_simplify_range(self):
        """Test simplifying commit range."""
        message = mock.Mock()
        message.attributes = {
            'source_id': 'oss-fuzz:123',
            'allocated_id': '2020-1337',
        }

        regress_result = osv.RegressResult(
            id='oss-fuzz:123',
            commit=('a2ba949290915d445d34d0e8e9de2e7ce38198fc:'
                    'eefe8ec3f1f90d0e684890e810f3f21e8500a4cd'),
            repo_url='https://repo.com/repo',
            issue_id='9001',
            project='project',
            ecosystem='ecosystem',
            summary='Heap-buffer-overflow in Foo',
            severity='MEDIUM',
            reference_urls=['https://url/'])
        regress_result.put()

        fix_result = osv.FixResult(
            id='oss-fuzz:123',
            commit=('b1c95a196f22d06fcf80df8c6691cd113d8fefff:'
                    '8d8242f545e9cec3e6d0d2e3f5bde8be1c659735'),
            repo_url='https://repo.com/repo',
            project='project',
            ecosystem='ecosystem',
            summary='Heap-buffer-overflow in Foo',
            details='DETAILS',
            severity='MEDIUM',
            reference_urls=['https://url/'])
        fix_result.put()

        oss_fuzz.process_impact_task('oss-fuzz:123', message)
        self.assertDictEqual(
            {
                'affected':
                ['branch-v0.1.1', 'branch_1_cherrypick_regress', 'v0.1.1'],
                'affected_fuzzy': ['0-1-1', '1', '0-1-1'],
                'additional_commit_ranges': [{
                    'introduced_in':
                    'eefe8ec3f1f90d0e684890e810f3f21e8500a4cd',
                    'fixed_in':
                    'b9b3fd4732695b83c3068b7b6a14bb372ec31f98'
                }, {
                    'introduced_in':
                    'febfac1940086bc1f6d3dc33fda0a1d1ba336209',
                    'fixed_in': None
                }],
                'fixed':
                '8d8242f545e9cec3e6d0d2e3f5bde8be1c659735',
                'regressed':
                'eefe8ec3f1f90d0e684890e810f3f21e8500a4cd',
                'repo_url':
                'https://repo.com/repo',
                'confidence':
                100,
                'issue_id':
                '9001',
                'last_modified':
                datetime.datetime(2021, 1, 1, 0, 0),
                'timestamp':
                datetime.datetime(2020, 1, 1),
                'source_id':
                'oss-fuzz:123',
                'project':
                'project',
                'ecosystem':
                'ecosystem',
                'summary':
                'Heap-buffer-overflow in Foo',
                'details':
                'DETAILS',
                'severity':
                'MEDIUM',
                'sort_key':
                '2020-0001337',
                'source_of_truth':
                osv.SourceOfTruth.INTERNAL,
                'reference_urls': ['https://url/'],
                'public':
                False,
                'status':
                osv.BugStatus.PROCESSED.value,
                'has_affected':
                True,
                'search_indices': ['project', '2020-1337', '2020', '1337'],
            },
            ndb.Key(osv.Bug, '2020-1337').get()._to_dict())
Example #11
0
    def test_zero_regression_range(self):
        """Test regression range with "0:X"."""
        message = mock.Mock()
        message.attributes = {
            'source_id': 'oss-fuzz:123',
            'allocated_id': '2020-1337',
        }

        regress_result = osv.RegressResult(
            id='oss-fuzz:123',
            commit='unknown:eefe8ec3f1f90d0e684890e810f3f21e8500a4cd',
            repo_url='https://repo.com/repo',
            issue_id='9001',
            project='project',
            ecosystem='ecosystem',
            summary='Heap-buffer-overflow in Foo',
            severity='MEDIUM',
            reference_urls=['https://url/'])
        regress_result.put()

        fix_result = osv.FixResult(
            id='oss-fuzz:123',
            commit='8d8242f545e9cec3e6d0d2e3f5bde8be1c659735',
            repo_url='https://repo.com/repo',
            project='project',
            ecosystem='ecosystem',
            summary='Heap-buffer-overflow in Foo',
            details='DETAILS',
            severity='MEDIUM',
            reference_urls=['https://url/'])
        fix_result.put()

        oss_fuzz.process_impact_task('oss-fuzz:123', message)
        self.assertDictEqual(
            {
                'affected':
                ['branch-v0.1.1', 'branch_1_cherrypick_regress', 'v0.1.1'],
                'affected_fuzzy': ['0-1-1', '1', '0-1-1'],
                'additional_commit_ranges': [],
                'fixed':
                '8d8242f545e9cec3e6d0d2e3f5bde8be1c659735',
                'regressed':
                'unknown:eefe8ec3f1f90d0e684890e810f3f21e8500a4cd',
                'repo_url':
                'https://repo.com/repo',
                'confidence':
                80,
                'issue_id':
                '9001',
                'last_modified':
                datetime.datetime(2021, 1, 1, 0, 0),
                'timestamp':
                datetime.datetime(2020, 1, 1),
                'source_id':
                'oss-fuzz:123',
                'project':
                'project',
                'ecosystem':
                'ecosystem',
                'summary':
                'Heap-buffer-overflow in Foo',
                'details':
                'DETAILS',
                'severity':
                'MEDIUM',
                'sort_key':
                '2020-0001337',
                'source_of_truth':
                osv.SourceOfTruth.INTERNAL,
                'reference_urls': ['https://url/'],
                'public':
                False,
                'status':
                osv.BugStatus.PROCESSED.value,
                'has_affected':
                True,
                'search_indices': ['project', '2020-1337', '2020', '1337'],
            },
            ndb.Key(osv.Bug, '2020-1337').get()._to_dict())

        affected_commits = list(osv.AffectedCommit.query())
        for commit in affected_commits:
            self.assertEqual(80, commit.confidence)
            self.assertEqual('project', commit.project)

        self.assertCountEqual([
            'ff8cc32ba60ad9cbb3b23f0a82aad96ebe9ff76b',
            'febfac1940086bc1f6d3dc33fda0a1d1ba336209',
            '4c155795426727ea05575bd5904321def23c03f4',
            'b1c95a196f22d06fcf80df8c6691cd113d8fefff',
            'eefe8ec3f1f90d0e684890e810f3f21e8500a4cd',
        ], [commit.commit for commit in affected_commits])
Example #12
0
    def test_update_add_fix(self):
        """Test basic update adding a fix."""
        fix_result = osv.FixResult(
            id='source:BLAH-124.yaml',
            commit='8d8242f545e9cec3e6d0d2e3f5bde8be1c659735')
        fix_result.put()
        task_runner = worker.TaskRunner(ndb_client, None, self.tmp_dir.name,
                                        None, None)
        message = mock.Mock()
        message.attributes = {
            'source':
            'source',
            'path':
            'BLAH-124.yaml',
            'original_sha256': ('80e0cb5e08fb624fc265c91729422cd8'
                                '8d1c0b1696990f9a6defe417101e6d6d'),
        }
        task_runner._source_update(message)

        repo = pygit2.Repository(self.remote_source_repo_path)
        commit = repo.head.peel()

        self.assertEqual('*****@*****.**', commit.author.email)
        self.assertEqual('OSV', commit.author.name)
        self.assertEqual('Update BLAH-124', commit.message)
        diff = repo.diff(commit.parents[0], commit)
        self.assertEqual(self._load_test_data('expected_add_fix.diff'),
                         diff.patch)

        self.assertDictEqual(
            {
                'additional_commit_ranges':
                [{
                    'fixed_in': 'b9b3fd4732695b83c3068b7b6a14bb372ec31f98',
                    'introduced_in': 'eefe8ec3f1f90d0e684890e810f3f21e8500a4cd'
                }, {
                    'fixed_in': '',
                    'introduced_in': 'febfac1940086bc1f6d3dc33fda0a1d1ba336209'
                }],
                'affected': [],
                'affected_fuzzy': [],
                'confidence':
                None,
                'details':
                'Blah blah blah\nBlah\n',
                'ecosystem':
                'golang',
                'fixed':
                '8d8242f545e9cec3e6d0d2e3f5bde8be1c659735',
                'has_affected':
                False,
                'issue_id':
                None,
                'last_modified':
                datetime.datetime(2021, 1, 1, 0, 0),
                'project':
                'blah.com/package',
                'public':
                None,
                'reference_urls': ['https://ref.com/ref'],
                'regressed':
                'eefe8ec3f1f90d0e684890e810f3f21e8500a4cd',
                'repo_url':
                None,
                'search_indices':
                ['blah.com/package', 'BLAH-124', 'BLAH', '124'],
                'severity':
                'HIGH',
                'sort_key':
                'BLAH-0000124',
                'source_id':
                'source:BLAH-124.yaml',
                'source_of_truth':
                osv.SourceOfTruth.SOURCE_REPO,
                'status':
                None,
                'summary':
                'A vulnerability',
                'timestamp':
                None
            },
            osv.Bug.get_by_id('BLAH-124')._to_dict())
Example #13
0
    def test_update_add_fix(self):
        """Test basic update adding a fix."""
        fix_result = osv.FixResult(
            id='source:BLAH-124.yaml',
            commit='8d8242f545e9cec3e6d0d2e3f5bde8be1c659735')
        fix_result.put()
        task_runner = worker.TaskRunner(ndb_client, None, self.tmp_dir.name,
                                        None, None)
        message = mock.Mock()
        message.attributes = {
            'source':
            'source',
            'path':
            'BLAH-124.yaml',
            'original_sha256': ('df9b0207ff2aa433d71869fa206b4884'
                                '071807d5dfddf8626b93da210b6572ef'),
        }
        task_runner._source_update(message)

        repo = pygit2.Repository(self.remote_source_repo_path)
        commit = repo.head.peel()

        self.assertEqual('*****@*****.**', commit.author.email)
        self.assertEqual('OSV', commit.author.name)
        self.assertEqual('Update BLAH-124', commit.message)
        diff = repo.diff(commit.parents[0], commit)
        self.assertEqual(self._load_test_data('expected_add_fix.diff'),
                         diff.patch)

        self.assertDictEqual(
            {
                'additional_commit_ranges':
                [{
                    'fixed_in': 'b9b3fd4732695b83c3068b7b6a14bb372ec31f98',
                    'introduced_in': 'eefe8ec3f1f90d0e684890e810f3f21e8500a4cd'
                }, {
                    'fixed_in': '',
                    'introduced_in': 'febfac1940086bc1f6d3dc33fda0a1d1ba336209'
                }],
                'affected': [],
                'affected_fuzzy': [],
                'confidence':
                None,
                'details':
                'Blah blah blah\nBlah\n',
                'ecosystem':
                'golang',
                'fixed':
                '8d8242f545e9cec3e6d0d2e3f5bde8be1c659735',
                'has_affected':
                False,
                'issue_id':
                None,
                'last_modified':
                datetime.datetime(2021, 1, 1, 0, 0),
                'project':
                'blah.com/package',
                'public':
                None,
                'reference_urls': ['https://ref.com/ref'],
                'regressed':
                'eefe8ec3f1f90d0e684890e810f3f21e8500a4cd',
                'repo_url':
                None,
                'search_indices':
                ['blah.com/package', 'BLAH-124', 'BLAH', '124'],
                'severity':
                'HIGH',
                'sort_key':
                'BLAH-0000124',
                'source_id':
                'source:BLAH-124.yaml',
                'source_of_truth':
                osv.SourceOfTruth.SOURCE_REPO,
                'status':
                None,
                'summary':
                'A vulnerability',
                'timestamp':
                None
            },
            osv.Bug.get_by_id('BLAH-124')._to_dict())

        affected_commits = list(osv.AffectedCommit.query())
        self.assertCountEqual([
            '4c155795426727ea05575bd5904321def23c03f4',
            'b1c95a196f22d06fcf80df8c6691cd113d8fefff',
            'eefe8ec3f1f90d0e684890e810f3f21e8500a4cd',
            'febfac1940086bc1f6d3dc33fda0a1d1ba336209',
            'ff8cc32ba60ad9cbb3b23f0a82aad96ebe9ff76b',
        ], [commit.commit for commit in affected_commits])
Example #14
0
    def test_fixed_range_too_long(self):
        """Test fixed range that's too long."""
        message = mock.Mock()
        message.attributes = {
            'source_id': 'oss-fuzz:123',
            'allocated_id': '2020-1337',
        }

        regress_result = osv.RegressResult(
            id='oss-fuzz:123',
            commit='eefe8ec3f1f90d0e684890e810f3f21e8500a4cd',
            repo_url='https://repo.com/repo',
            issue_id='9001',
            project='project',
            ecosystem='ecosystem',
            summary='Heap-buffer-overflow in Foo',
            severity='MEDIUM',
            reference_urls=['https://url/'])
        regress_result.put()

        fix_result = osv.FixResult(
            id='oss-fuzz:123',
            commit=('eefe8ec3f1f90d0e684890e810f3f21e8500a4cd:'
                    'b587c21c36a84e16cfc6b39eb68578d43b5281ad'),
            repo_url='https://repo.com/repo',
            project='project',
            ecosystem='ecosystem',
            summary='Heap-buffer-overflow in Foo',
            details='DETAILS',
            severity='MEDIUM',
            reference_urls=['https://url/'])
        fix_result.put()

        oss_fuzz.process_impact_task('oss-fuzz:123', message)
        self.assertDictEqual(
            {
                'affected': [
                    'branch-v0.1.1', 'branch-v0.1.1-with-fix',
                    'branch_1_cherrypick_regress', 'v0.1.1', 'v0.2'
                ],
                'affected_fuzzy': ['0-1-1', '0-1-1', '1', '0-1-1', '0-2'],
                'additional_commit_ranges': [],
                'regressed':
                'eefe8ec3f1f90d0e684890e810f3f21e8500a4cd',
                'fixed': ('eefe8ec3f1f90d0e684890e810f3f21e8500a4cd:'
                          'b587c21c36a84e16cfc6b39eb68578d43b5281ad'),
                'repo_url':
                'https://repo.com/repo',
                'confidence':
                30,
                'issue_id':
                '9001',
                'last_modified':
                datetime.datetime(2021, 1, 1, 0, 0),
                'timestamp':
                datetime.datetime(2020, 1, 1),
                'source_id':
                'oss-fuzz:123',
                'project':
                'project',
                'ecosystem':
                'ecosystem',
                'summary':
                'Heap-buffer-overflow in Foo',
                'details':
                'DETAILS',
                'reference_urls': ['https://url/'],
                'severity':
                'MEDIUM',
                'sort_key':
                '2020-0001337',
                'public':
                False,
                'status':
                osv.BugStatus.PROCESSED.value,
                'has_affected':
                True,
                'search_indices': ['project', '2020-1337', '2020', '1337'],
            },
            ndb.Key(osv.Bug, '2020-1337').get()._to_dict())

        affected_commits = list(osv.AffectedCommit.query())
        for commit in affected_commits:
            self.assertEqual(30, commit.confidence)
            self.assertEqual('project', commit.project)

        self.assertCountEqual([
            'ff8cc32ba60ad9cbb3b23f0a82aad96ebe9ff76b',
            'febfac1940086bc1f6d3dc33fda0a1d1ba336209',
            '4c155795426727ea05575bd5904321def23c03f4',
            'b1c95a196f22d06fcf80df8c6691cd113d8fefff',
            'eefe8ec3f1f90d0e684890e810f3f21e8500a4cd',
            '8d8242f545e9cec3e6d0d2e3f5bde8be1c659735',
            '3ea6feea9bb853596c727abab309476cc07d1505',
            '36f0bd9549298b44f9ff2496c9dd1326b3a9d0e2',
        ], [commit.commit for commit in affected_commits])