nebius/SWE-rebench-V2-PRs huggingface dataset:
Repository: G-Rath/osv-detector
Pull request #58 (2022-03-11 04:12:00)

feat: support OSV advisories with just `versions` array in affected
Needed for #53, as some advisories only have `versions` (typically for those with single exact versions that are vulnerable)


Patch:
diff --git a/detector/database/osv.go b/detector/database/osv.go
index 79f9500..af8fda2 100644
--- a/detector/database/osv.go
+++ b/detector/database/osv.go
@@ -100,9 +100,22 @@ type Reference struct {
 	URL  string `json:"url"`
 }
 
+type Versions []string
+
+func (vs Versions) includes(v string) bool {
+	for _, v2 := range vs {
+		if v == v2 {
+			return true
+		}
+	}
+
+	return false
+}
+
 type Affected struct {
-	Package Package `json:"package"`
-	Ranges  Affects `json:"ranges,omitempty"`
+	Package  Package  `json:"package"`
+	Versions Versions `json:"versions"`
+	Ranges   Affects  `json:"ranges,omitempty"`
 }
 
 // OSV represents an OSV style JSON vulnerability database entry
@@ -146,16 +159,20 @@ func (osv *OSV) IsAffected(pkg detector.PackageDetails) bool {
 	for _, affected := range osv.Affected {
 		if affected.Package.Ecosystem == pkg.Ecosystem &&
 			affected.Package.NormalizedName() == pkg.Name {
-			if len(affected.Ranges) == 0 {
+			if len(affected.Ranges) == 0 && len(affected.Versions) == 0 {
 				_, _ = fmt.Fprintf(
 					os.Stderr,
-					"%s does not have any ranges - this is probably a mistake!\n",
+					"%s does not have any ranges or versions - this is probably a mistake!\n",
 					osv.ID,
 				)
 
 				continue
 			}
 
+			if affected.Versions.includes(pkg.Version) {
+				return true
+			}
+
 			if affected.Ranges.affectsVersion(pkg.Version) {
 				return true
 			}


Test patch:
diff --git a/detector/database/osv_test.go b/detector/database/osv_test.go
index b90cfa7..54e6e8c 100644
--- a/detector/database/osv_test.go
+++ b/detector/database/osv_test.go
@@ -472,3 +472,19 @@ func TestOSV_IsAffected_AffectsWithSemver_MultipleAffected(t *testing.T) {
 		expectIsAffected(t, osv, v, false)
 	}
 }
+
+func TestOSV_IsAffected_OnlyVersions(t *testing.T) {
+	t.Parallel()
+
+	osv := buildOSVWithAffected(
+		database.Affected{
+			Package:  database.Package{Ecosystem: parsers.NpmEcosystem, Name: "my-package"},
+			Versions: []string{"1.0.0"},
+		},
+	)
+
+	expectIsAffected(t, osv, "0.0.0", false)
+	expectIsAffected(t, osv, "1.0.0", true)
+	expectIsAffected(t, osv, "1.0.0-beta1", false)
+	expectIsAffected(t, osv, "1.1.0", false)
+}
Repository: G-Rath/osv-detector
Pull request #67 (2022-03-12 23:15:35)

refactor: rename `lockfile.TryParse` to `lockfile.Parse`
It's a little more accurate, as the "try" part is represented by it returning `error`.


Patch:
diff --git a/internal/lockfile/parsers.go b/internal/lockfile/parse.go
similarity index 84%
rename from internal/lockfile/parsers.go
rename to internal/lockfile/parse.go
index 4523400..0c663df 100644
--- a/internal/lockfile/parsers.go
+++ b/internal/lockfile/parse.go
@@ -60,7 +60,12 @@ func (ps Packages) Ecosystems() []Ecosystem {
 	return slicedEcosystems
 }
 
-func TryParse(pathToLockfile string, parseAs string) (Packages, error) {
+// Parse attempts to extract a collection of package details from a lockfile,
+// using one of the native parsers.
+//
+// The parser is selected based on the name of the file, which can be overridden
+// with the "parseAs" parameter.
+func Parse(pathToLockfile string, parseAs string) (Packages, error) {
 	if parseAs == "" {
 		parseAs = path.Base(pathToLockfile)
 	}
diff --git a/main.go b/main.go
index a608f34..d426bdf 100644
--- a/main.go
+++ b/main.go
@@ -125,7 +125,7 @@ func main() {
 
 	pathToLockOrDirectory := flag.Arg(0)
 
-	packages, err := lockfile.TryParse(pathToLockOrDirectory, *parseAs)
+	packages, err := lockfile.Parse(pathToLockOrDirectory, *parseAs)
 
 	if err != nil {
 		_, _ = fmt.Fprintf(os.Stderr, "Error, %s\n", err)


Test patch:
diff --git a/internal/lockfile/parsers_test.go b/internal/lockfile/parse_test.go
similarity index 95%
rename from internal/lockfile/parsers_test.go
rename to internal/lockfile/parse_test.go
index df637ed..4f770c0 100644
--- a/internal/lockfile/parsers_test.go
+++ b/internal/lockfile/parse_test.go
@@ -52,7 +52,7 @@ func TestTryParse_FindsExpectedParsers(t *testing.T) {
 	count := 0
 
 	for _, file := range lockfiles {
-		_, err := lockfile.TryParse("/path/to/my/"+file, "")
+		_, err := lockfile.Parse("/path/to/my/"+file, "")
 
 		if errors.Is(err, lockfile.ErrParserNotFound) {
 			t.Errorf("No parser was found for %s", file)
Repository: G-Rath/osv-detector
Pull request #88 (2022-05-02 19:34:36)

fix: handle plural & singular form properly
If anyone can come up with a better name to `Form`, I'd be interested in hearing it 😅 


Patch:
diff --git a/internal/reporter/report.go b/internal/reporter/report.go
index 32695d9..61f63f3 100644
--- a/internal/reporter/report.go
+++ b/internal/reporter/report.go
@@ -61,8 +61,18 @@ func (r Report) formatLineByLine() string {
 	return strings.Join(lines, "\n")
 }
 
+func Form(count int, singular, plural string) string {
+	if count == 1 {
+		return singular
+	}
+
+	return plural
+}
+
 func (r Report) ToString() string {
-	if r.countKnownVulnerabilities() == 0 {
+	count := r.countKnownVulnerabilities()
+
+	if count == 0 {
 		return fmt.Sprintf("%s\n", color.GreenString("  no known vulnerabilities found"))
 	}
 
@@ -71,8 +81,9 @@ func (r Report) ToString() string {
 
 	out += fmt.Sprintf("\n  %s\n",
 		color.RedString(
-			"%d known vulnerabilities found in %s",
-			r.countKnownVulnerabilities(),
+			"%d known %s found in %s",
+			count,
+			Form(count, "vulnerability", "vulnerabilities"),
 			r.FilePath,
 		),
 	)
diff --git a/main.go b/main.go
index 2642c5c..19325f0 100644
--- a/main.go
+++ b/main.go
@@ -83,9 +83,12 @@ func loadEcosystemDatabases(r *reporter.Reporter, ecosystems []internal.Ecosyste
 			return dbs, fmt.Errorf("could not load database: %w", err)
 		}
 
+		count := len(db.Vulnerabilities(true))
+
 		r.PrintText(fmt.Sprintf(
-			" (%s vulnerabilities, including withdrawn - last updated %s)\n",
-			color.YellowString("%d", len(db.Vulnerabilities(true))),
+			" (%s %s, including withdrawn - last updated %s)\n",
+			color.YellowString("%d", count),
+			reporter.Form(count, "vulnerability", "vulnerabilities"),
 			db.UpdatedAt,
 		))
 
@@ -231,9 +234,10 @@ func run() int {
 		}
 
 		r.PrintText(fmt.Sprintf(
-			"%s: found %s packages\n",
+			"%s: found %s %s\n",
 			color.MagentaString("%s", lockf.FilePath),
 			color.YellowString("%d", len(lockf.Packages)),
+			reporter.Form(len(lockf.Packages), "package", "packages"),
 		))
 
 		if *listPackages {


Test patch:
diff --git a/internal/reporter/report_test.go b/internal/reporter/report_test.go
index 0bea4bf..5b28c4f 100644
--- a/internal/reporter/report_test.go
+++ b/internal/reporter/report_test.go
@@ -109,14 +109,14 @@ func TestReport_ToString_NoVulnerabilities(t *testing.T) {
 	}
 }
 
-func TestReport_ToString_Vulnerabilities(t *testing.T) {
+func TestReport_ToString_OneVulnerability(t *testing.T) {
 	t.Parallel()
 
 	expected := strings.Join([]string{
 		"  my-package@1.2.3 is affected by the following vulnerabilities:",
 		"    GHSA-1: This is a vulnerability! (https://github.com/advisories/GHSA-1)",
 		"",
-		"  1 known vulnerabilities found in /path/to/my/lock",
+		"  1 known vulnerability found in /path/to/my/lock",
 		"",
 	}, "\n")