Skip to content

Commit f5fbf57

Browse files
authored
refactor(vulnfeeds): git commit resolution code for better reusability (#4052)
Part of splitting logic from #3951
1 parent 03ee599 commit f5fbf57

File tree

4 files changed

+48
-41
lines changed

4 files changed

+48
-41
lines changed

vulnfeeds/cves/versions.go

Lines changed: 27 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -515,44 +515,51 @@ func ValidateAndCanonicalizeLink(link string, httpClient *http.Client) (canonica
515515
}
516516

517517
// For URLs referencing commits in supported Git repository hosts, return a cloneable AffectedCommit.
518-
func ExtractGitCommit(link string, commitType models.CommitType, httpClient *http.Client) (ac models.AffectedCommit, err error) {
519-
r, err := Repo(link)
518+
func extractGitAffectedCommit(link string, commitType models.CommitType, httpClient *http.Client) (models.AffectedCommit, error) {
519+
var ac models.AffectedCommit
520+
c, r, err := ExtractGitCommit(link, httpClient, 0)
520521
if err != nil {
521522
return ac, err
522523
}
523524

525+
ac.SetRepo(r)
526+
527+
models.SetCommitByType(&ac, commitType, c)
528+
529+
return ac, nil
530+
}
531+
532+
func ExtractGitCommit(link string, httpClient *http.Client, depth int) (string, string, error) {
533+
if depth > 10 {
534+
return "", "", fmt.Errorf("max recursion depth exceeded for %s", link)
535+
}
536+
var commit string
537+
r, err := Repo(link)
538+
if err != nil {
539+
return "", "", err
540+
}
541+
524542
c, err := Commit(link)
525543
if err != nil {
526-
return ac, err
544+
return "", "", err
527545
}
528546

547+
commit = c
548+
529549
// If URL doesn't validate, treat it as linkrot.
530550
possiblyDifferentLink, err := ValidateAndCanonicalizeLink(link, httpClient)
531551
if err != nil {
532-
return ac, err
552+
return "", "", err
533553
}
534554

535555
// restart the entire extraction process when the URL changes (i.e. handle a
536556
// redirect to a completely different host, instead of a redirect within
537557
// GitHub)
538558
if possiblyDifferentLink != link {
539-
return ExtractGitCommit(possiblyDifferentLink, commitType, httpClient)
559+
return ExtractGitCommit(possiblyDifferentLink, httpClient, depth+1)
540560
}
541561

542-
ac.SetRepo(r)
543-
544-
switch commitType {
545-
case models.Introduced:
546-
ac.SetIntroduced(c)
547-
case models.LastAffected:
548-
ac.SetLastAffected(c)
549-
case models.Limit:
550-
ac.SetLimit(c)
551-
case models.Fixed:
552-
ac.SetFixed(c)
553-
}
554-
555-
return ac, nil
562+
return commit, r, nil
556563
}
557564

558565
func HasVersion(validVersions []string, version string) bool {
@@ -676,7 +683,7 @@ func deduplicateAffectedCommits(commits []models.AffectedCommit) []models.Affect
676683
func ExtractVersionInfo(cve CVE, validVersions []string, httpClient *http.Client) (v models.VersionInfo, notes []string) {
677684
for _, reference := range cve.References {
678685
// (Potentially faulty) Assumption: All viable Git commit reference links are fix commits.
679-
if commit, err := ExtractGitCommit(reference.URL, models.Fixed, httpClient); err == nil {
686+
if commit, err := extractGitAffectedCommit(reference.URL, models.Fixed, httpClient); err == nil {
680687
v.AffectedCommits = append(v.AffectedCommits, commit)
681688
}
682689
}

vulnfeeds/cves/versions_test.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -686,20 +686,20 @@ func TestExtractGitCommit(t *testing.T) {
686686
t.Skipf("test %q: running on Cloud Build", tc.description)
687687
}
688688
if time.Now().Before(tc.disableExpiryDate) {
689-
t.Skipf("test %q: extractGitCommit for %q (%q) has been skipped due to known outage and will be reenabled on %s.", tc.description, tc.inputLink, tc.inputCommitType, tc.disableExpiryDate)
689+
t.Skipf("test %q: extractGitAffectedCommit for %q (%q) has been skipped due to known outage and will be reenabled on %s.", tc.description, tc.inputLink, tc.inputCommitType, tc.disableExpiryDate)
690690
}
691691
if !tc.disableExpiryDate.IsZero() && time.Now().After(tc.disableExpiryDate) {
692-
t.Logf("test %q: extractGitCommit(%q, %q) has been enabled on %s.", tc.description, tc.inputLink, tc.inputCommitType, tc.disableExpiryDate)
692+
t.Logf("test %q: extractGitAffectedCommit(%q, %q) has been enabled on %s.", tc.description, tc.inputLink, tc.inputCommitType, tc.disableExpiryDate)
693693
}
694-
got, err := ExtractGitCommit(tc.inputLink, tc.inputCommitType, client)
694+
got, err := extractGitAffectedCommit(tc.inputLink, tc.inputCommitType, client)
695695
if err != nil && !tc.expectFailure {
696-
t.Errorf("test %q: extractGitCommit for %q (%q) errored unexpectedly: %#v", tc.description, tc.inputLink, tc.inputCommitType, err)
696+
t.Errorf("test %q: extractGitAffectedCommit for %q (%q) errored unexpectedly: %#v", tc.description, tc.inputLink, tc.inputCommitType, err)
697697
}
698698
if err == nil && tc.expectFailure {
699-
t.Errorf("test %q: extractGitCommit for %q (%q) did not error as unexpected!", tc.description, tc.inputLink, tc.inputCommitType)
699+
t.Errorf("test %q: extractGitAffectedCommit for %q (%q) did not error as unexpected!", tc.description, tc.inputLink, tc.inputCommitType)
700700
}
701701
if !reflect.DeepEqual(got, tc.expectedAffectedCommit) {
702-
t.Errorf("test %q: extractGitCommit for %q was incorrect, got: %#v, expected: %#v", tc.description, tc.inputLink, got, tc.expectedAffectedCommit)
702+
t.Errorf("test %q: extractGitAffectedCommit for %q was incorrect, got: %#v, expected: %#v", tc.description, tc.inputLink, got, tc.expectedAffectedCommit)
703703
}
704704
})
705705
}

vulnfeeds/git/versions.go

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -25,20 +25,6 @@ import (
2525

2626
var versionRangeRegex = regexp.MustCompile(`^(>=|<=|~|\^|>|<|=)\s*([0-9a-zA-Z\.\-]+)(?:,\s*(>=|<=|~|\^|>|<|=)\s*([0-9a-zA-Z\.\-]+))?$`) // Used to parse version strings from the GitHub CNA.
2727

28-
// setCommitByType sets the appropriate commit field on an AffectedCommit based on the CommitType.
29-
func setCommitByType(ac *models.AffectedCommit, commitType models.CommitType, commitHash string) {
30-
switch commitType {
31-
case models.Introduced:
32-
ac.SetIntroduced(commitHash)
33-
case models.LastAffected:
34-
ac.SetLastAffected(commitHash)
35-
case models.Limit:
36-
ac.SetLimit(commitHash)
37-
case models.Fixed:
38-
ac.SetFixed(commitHash)
39-
}
40-
}
41-
4228
// findFuzzyCommit takes an already normalized version and the mapping of repo tags to
4329
// normalized tags and commits, and performs fuzzy matching to find a commit hash.
4430
func findFuzzyCommit(normalizedVersion string, normalizedTags map[string]NormalizedTag) (string, bool) {
@@ -87,7 +73,7 @@ func VersionToAffectedCommit(version string, repo string, commitType models.Comm
8773
return ac, err
8874
}
8975
ac.SetRepo(repo)
90-
setCommitByType(&ac, commitType, commitHash)
76+
models.SetCommitByType(&ac, commitType, commitHash)
9177

9278
return ac, nil
9379
}

vulnfeeds/models/types.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,20 @@ type AffectedCommit struct {
1515
LastAffected string `json:"last_affected,omitempty" yaml:"last_affected,omitempty"`
1616
}
1717

18+
// SetCommitByType sets the appropriate commit field on an AffectedCommit based on the CommitType.
19+
func SetCommitByType(ac *AffectedCommit, commitType CommitType, commitHash string) {
20+
switch commitType {
21+
case Introduced:
22+
ac.SetIntroduced(commitHash)
23+
case LastAffected:
24+
ac.SetLastAffected(commitHash)
25+
case Limit:
26+
ac.SetLimit(commitHash)
27+
case Fixed:
28+
ac.SetFixed(commitHash)
29+
}
30+
}
31+
1832
func (ac *AffectedCommit) SetRepo(repo string) {
1933
// GitHub.com repos are demonstrably case-insensitive, and frequently
2034
// expressed in URLs with varying cases, so normalize them to lowercase.

0 commit comments

Comments
 (0)