osv: don't prefix semver strings

In order to match the current state of the public vulnerability format,
don't prefix SEMVER strings with 'v' or 'go' so that they are valid.

Also update osv.Affects.AffectsSemver so that it can take SEMVER strings
which either do or don't have the prefix.

Change-Id: I879f5c0387338290fe0aaa7ab8391e1c19de681e
Reviewed-on: https://go-review.googlesource.com/c/vulndb/+/326489
Trust: Roland Shoemaker <roland@golang.org>
Run-TryBot: Roland Shoemaker <roland@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Filippo Valsorda <filippo@golang.org>
diff --git a/osv/json.go b/osv/json.go
index 660cda7..8e19f9a 100644
--- a/osv/json.go
+++ b/osv/json.go
@@ -22,6 +22,7 @@
 package osv
 
 import (
+	"strings"
 	"time"
 
 	"golang.org/x/mod/semver"
@@ -58,26 +59,48 @@
 	Fixed      string           `json:"fixed"`
 }
 
+// addSemverPrefix adds a 'v' prefix to s if it isn't already prefixed
+// with 'v' or 'go'. This allows us to easily test go-style SEMVER
+// strings against normal SEMVER strings.
+func addSemverPrefix(s string) string {
+	if !strings.HasPrefix(s, "v") && !strings.HasPrefix(s, "go") {
+		return "v" + s
+	}
+	return s
+}
+
 func (ar AffectsRange) containsSemver(v string) bool {
 	if ar.Type != TypeSemver {
 		return false
 	}
 
-	return (ar.Introduced == "" || semver.Compare(v, ar.Introduced) >= 0) &&
-		(ar.Fixed == "" || semver.Compare(v, ar.Fixed) < 0)
+	// Strip and then add the semver prefix so we can support bare versions,
+	// versions prefixed with 'v', and versions prefixed with 'go'.
+	v = addSemverPrefix(removeSemverPrefix(v))
+
+	return (ar.Introduced == "" || semver.Compare(v, addSemverPrefix(ar.Introduced)) >= 0) &&
+		(ar.Fixed == "" || semver.Compare(v, addSemverPrefix(ar.Fixed)) < 0)
 }
 
 type Affects struct {
 	Ranges []AffectsRange `json:"ranges,omitempty"`
 }
 
+// removeSemverPrefix removes the 'v' or 'go' prefixes from go-style
+// SEMVER strings, for usage in the public vulnerability format.
+func removeSemverPrefix(s string) string {
+	s = strings.TrimPrefix(s, "v")
+	s = strings.TrimPrefix(s, "go")
+	return s
+}
+
 func generateAffects(versions []report.VersionRange) Affects {
 	a := Affects{}
 	for _, v := range versions {
 		a.Ranges = append(a.Ranges, AffectsRange{
 			Type:       TypeSemver,
-			Introduced: v.Introduced,
-			Fixed:      v.Fixed,
+			Introduced: removeSemverPrefix(v.Introduced),
+			Fixed:      removeSemverPrefix(v.Fixed),
 		})
 	}
 	return a
diff --git a/osv/json_test.go b/osv/json_test.go
index 39bfa5d..ae0d69b 100644
--- a/osv/json_test.go
+++ b/osv/json_test.go
@@ -57,16 +57,16 @@
 				Ranges: []AffectsRange{
 					{
 						Type:  TypeSemver,
-						Fixed: "v2.1.1",
+						Fixed: "2.1.1",
 					},
 					{
 						Type:       TypeSemver,
-						Introduced: "v2.3.4",
-						Fixed:      "v2.3.5",
+						Introduced: "2.3.4",
+						Fixed:      "2.3.5",
 					},
 					{
 						Type:       TypeSemver,
-						Introduced: "v2.5.0",
+						Introduced: "2.5.0",
 					},
 				},
 			},
@@ -96,16 +96,16 @@
 				Ranges: []AffectsRange{
 					{
 						Type:  TypeSemver,
-						Fixed: "v2.1.1",
+						Fixed: "2.1.1",
 					},
 					{
 						Type:       TypeSemver,
-						Introduced: "v2.3.4",
-						Fixed:      "v2.3.5",
+						Introduced: "2.3.4",
+						Fixed:      "2.3.5",
 					},
 					{
 						Type:       TypeSemver,
-						Introduced: "v2.5.0",
+						Introduced: "2.5.0",
 					},
 				},
 			},
@@ -146,7 +146,7 @@
 			// v1.0.0 < v2.0.0
 			affects: Affects{
 				Ranges: []AffectsRange{
-					{Type: TypeSemver, Fixed: "v2.0.0"},
+					{Type: TypeSemver, Fixed: "2.0.0"},
 				},
 			},
 			version: "v1.0.0",
@@ -156,7 +156,7 @@
 			// v0.0.1 <= v1.0.0
 			affects: Affects{
 				Ranges: []AffectsRange{
-					{Type: TypeSemver, Introduced: "v0.0.1"},
+					{Type: TypeSemver, Introduced: "0.0.1"},
 				},
 			},
 			version: "v1.0.0",
@@ -166,7 +166,7 @@
 			// v1.0.0 <= v1.0.0
 			affects: Affects{
 				Ranges: []AffectsRange{
-					{Type: TypeSemver, Introduced: "v1.0.0"},
+					{Type: TypeSemver, Introduced: "1.0.0"},
 				},
 			},
 			version: "v1.0.0",
@@ -176,7 +176,7 @@
 			// v1.0.0 <= v1.0.0 < v2.0.0
 			affects: Affects{
 				Ranges: []AffectsRange{
-					{Type: TypeSemver, Introduced: "v1.0.0", Fixed: "v2.0.0"},
+					{Type: TypeSemver, Introduced: "1.0.0", Fixed: "2.0.0"},
 				},
 			},
 			version: "v1.0.0",
@@ -186,7 +186,7 @@
 			// v0.0.1 <= v1.0.0 < v2.0.0
 			affects: Affects{
 				Ranges: []AffectsRange{
-					{Type: TypeSemver, Introduced: "v0.0.1", Fixed: "v2.0.0"},
+					{Type: TypeSemver, Introduced: "0.0.1", Fixed: "2.0.0"},
 				},
 			},
 			version: "v1.0.0",
@@ -196,7 +196,7 @@
 			// v2.0.0 < v3.0.0
 			affects: Affects{
 				Ranges: []AffectsRange{
-					{Type: TypeSemver, Introduced: "v1.0.0", Fixed: "v2.0.0"},
+					{Type: TypeSemver, Introduced: "1.0.0", Fixed: "2.0.0"},
 				},
 			},
 			version: "v3.0.0",
@@ -206,8 +206,8 @@
 			// Multiple ranges
 			affects: Affects{
 				Ranges: []AffectsRange{
-					{Type: TypeSemver, Introduced: "v1.0.0", Fixed: "v2.0.0"},
-					{Type: TypeSemver, Introduced: "v3.0.0"},
+					{Type: TypeSemver, Introduced: "1.0.0", Fixed: "2.0.0"},
+					{Type: TypeSemver, Introduced: "3.0.0"},
 				},
 			},
 			version: "v3.0.0",
@@ -217,7 +217,7 @@
 			// Wrong type range
 			affects: Affects{
 				Ranges: []AffectsRange{
-					{Type: TypeUnspecified, Introduced: "v3.0.0"},
+					{Type: TypeUnspecified, Introduced: "3.0.0"},
 				},
 			},
 			version: "v3.0.0",
@@ -227,8 +227,8 @@
 			// Semver ranges don't match
 			affects: Affects{
 				Ranges: []AffectsRange{
-					{Type: TypeUnspecified, Introduced: "v3.0.0"},
-					{Type: TypeSemver, Introduced: "v4.0.0"},
+					{Type: TypeUnspecified, Introduced: "3.0.0"},
+					{Type: TypeSemver, Introduced: "4.0.0"},
 				},
 			},
 			version: "v3.0.0",
@@ -238,13 +238,23 @@
 			// Semver ranges do match
 			affects: Affects{
 				Ranges: []AffectsRange{
-					{Type: TypeUnspecified, Introduced: "v3.0.0"},
-					{Type: TypeSemver, Introduced: "v3.0.0"},
+					{Type: TypeUnspecified, Introduced: "3.0.0"},
+					{Type: TypeSemver, Introduced: "3.0.0"},
 				},
 			},
 			version: "v3.0.0",
 			want:    true,
 		},
+		{
+			// Semver ranges match (go prefix)
+			affects: Affects{
+				Ranges: []AffectsRange{
+					{Type: TypeSemver, Introduced: "3.0.0"},
+				},
+			},
+			version: "go3.0.1",
+			want:    true,
+		},
 	}
 
 	for _, c := range cases {