Repository: google/osv-scanner
Pull request #493 (2023-08-17 19:52:11)

fix: don't error if local db directory already exists
Part of #491


Patch:
diff --git a/internal/local/check.go b/internal/local/check.go
index 5408e71..ccf866a 100644
--- a/internal/local/check.go
+++ b/internal/local/check.go
@@ -73,7 +73,7 @@ func setupLocalDBDirectory(localDBPath string) (string, error) {
 		}
 	}
 
-	err = os.Mkdir(path.Join(localDBPath, "osv-scanner"), 0750)
+	err = os.MkdirAll(path.Join(localDBPath, "osv-scanner"), 0750)
 
 	if err == nil {
 		return path.Join(localDBPath, "osv-scanner"), nil
diff --git a/pkg/models/vulnerability.go b/pkg/models/vulnerability.go
index e92d423..1d92217 100644
--- a/pkg/models/vulnerability.go
+++ b/pkg/models/vulnerability.go
@@ -207,7 +207,18 @@ func (ar Range) containsVersion(pkg lockfile.PackageDetails) bool {
 	vp := semantic.MustParse(pkg.Version, pkg.CompareAs)
 
 	sort.Slice(ar.Events, func(i, j int) bool {
-		return semantic.MustParse(ar.Events[i].version(), pkg.CompareAs).CompareStr(ar.Events[j].version()) < 0
+		a := ar.Events[i]
+		b := ar.Events[j]
+
+		if a.Introduced == "0" {
+			return true
+		}
+
+		if b.Introduced == "0" {
+			return false
+		}
+
+		return semantic.MustParse(a.version(), pkg.CompareAs).CompareStr(b.version()) < 0
 	})
 
 	var affected bool


Test patch:
diff --git a/cmd/osv-scanner/main_test.go b/cmd/osv-scanner/main_test.go
index 9c82b48..dd03dcd 100644
--- a/cmd/osv-scanner/main_test.go
+++ b/cmd/osv-scanner/main_test.go
@@ -838,6 +838,9 @@ func TestRun_LocalDatabases(t *testing.T) {
 			tt.args = []string{"", "--experimental-local-db-path", testDir}
 			tt.args = append(tt.args, old[1:]...)
 
+			// run each test twice since they should provide the same output,
+			// and the second run should be fast as the db is already available
+			testCli(t, tt)
 			testCli(t, tt)
 		})
 	}
diff --git a/pkg/models/vulnerability_test.go b/pkg/models/vulnerability_test.go
index 14a3992..1303e07 100644
--- a/pkg/models/vulnerability_test.go
+++ b/pkg/models/vulnerability_test.go
@@ -593,6 +593,41 @@ func TestOSV_IsAffected_AffectsWithEcosystem_Unsorted(t *testing.T) {
 
 	// an empty version should always be treated as affected
 	expectIsAffected(t, vuln, "", true)
+
+	// zeros with build strings
+	vuln = buildOSVWithAffected(
+		models.Affected{
+			// golang.org/x/sys
+			Package: models.Package{Ecosystem: models.EcosystemNPM, Name: "my-package"},
+			Ranges: []models.Range{
+				buildEcosystemAffectsRange(
+					models.Event{Fixed: "0.0.0-20220412211240-33da011f77ad"},
+					models.Event{Introduced: "0"},
+				),
+			},
+		},
+		models.Affected{
+			// golang.org/x/net
+			Package: models.Package{Ecosystem: models.EcosystemNPM, Name: "my-package"},
+			Ranges: []models.Range{
+				buildEcosystemAffectsRange(
+					models.Event{Introduced: "0.0.0-20180925071336-cf3bd585ca2a"},
+					models.Event{Fixed: "0"},
+				),
+			},
+		},
+	)
+
+	for _, v := range []string{"0.0.0", "0.14.0"} {
+		expectIsAffected(t, vuln, v, false)
+	}
+
+	for _, v := range []string{"0.0.0-20180925071336-cf3bd585ca2a"} {
+		expectIsAffected(t, vuln, v, true)
+	}
+
+	// an empty version should always be treated as affected
+	expectIsAffected(t, vuln, "", true)
 }
 
 func TestOSV_IsAffected_AffectsWithSemver_DifferentEcosystem(t *testing.T) {
@@ -835,6 +870,44 @@ func TestOSV_IsAffected_AffectsWithSemver_Unsorted(t *testing.T) {
 
 	// an empty version should always be treated as affected
 	expectIsAffected(t, vuln, "", true)
+
+	// an empty version should always be treated as affected
+	expectIsAffected(t, vuln, "", true)
+
+	// zeros with build strings
+	vuln = buildOSVWithAffected(
+		models.Affected{
+			// golang.org/x/sys
+			Package: models.Package{Ecosystem: models.EcosystemNPM, Name: "my-package"},
+			Ranges: []models.Range{
+				buildSemverAffectsRange(
+					models.Event{Fixed: "0.0.0-20220412211240-33da011f77ad"},
+					models.Event{Introduced: "0"},
+				),
+			},
+		},
+		models.Affected{
+			// golang.org/x/net
+			Package: models.Package{Ecosystem: models.EcosystemNPM, Name: "my-package"},
+			Ranges: []models.Range{
+				buildSemverAffectsRange(
+					models.Event{Introduced: "0.0.0-20180925071336-cf3bd585ca2a"},
+					models.Event{Fixed: "0"},
+				),
+			},
+		},
+	)
+
+	for _, v := range []string{"0.0.0", "0.14.0"} {
+		expectIsAffected(t, vuln, v, false)
+	}
+
+	for _, v := range []string{"0.0.0-20180925071336-cf3bd585ca2a"} {
+		expectIsAffected(t, vuln, v, true)
+	}
+
+	// an empty version should always be treated as affected
+	expectIsAffected(t, vuln, "", true)
 }
 
 func TestOSV_IsAffected_OnlyVersions(t *testing.T) {