internal: add consts for artificial stdlib/toolchain module names

And replace importPathInStdlib with module path name comparison.

Change-Id: I7751ae8582865f2979492808a2c8a82ba9f2c0b0
Reviewed-on: https://go-review.googlesource.com/c/vuln/+/440215
Run-TryBot: Hyang-Ah Hana Kim <hyangah@gmail.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Jonathan Amsterdam <jba@google.com>
diff --git a/client/client.go b/client/client.go
index 053e2a5..31a5e34 100644
--- a/client/client.go
+++ b/client/client.go
@@ -314,8 +314,8 @@
 // mustn't pass them to module.EscapePath.
 // Keep in sync with vulndb/internal/database/generate.go.
 var specialCaseModulePaths = map[string]bool{
-	"stdlib":    true,
-	"toolchain": true,
+	internal.GoStdModulePath: true,
+	internal.GoCmdModulePath: true,
 }
 
 // EscapeModulePath should be called by cache implementations or other users of
diff --git a/internal/govulncheck/run.go b/internal/govulncheck/run.go
index 039b582..1b62670 100644
--- a/internal/govulncheck/run.go
+++ b/internal/govulncheck/run.go
@@ -163,7 +163,7 @@
 		id := v0.OSV.ID
 		details := wrap(v0.OSV.Details, 80-labelWidth)
 		found := foundVersion(v0.ModPath, v0.PkgPath, ci)
-		fixed := fixedVersion(v0.PkgPath, v0.OSV.Affected)
+		fixed := fixedVersion(v0.ModPath, v0.PkgPath, v0.OSV.Affected)
 
 		// TODO(https://go.dev/issue/56042): add stacks to govulncheck.Result.
 		var stacks string
@@ -186,7 +186,7 @@
 		fmt.Println(informationalMessage)
 		for idx, vuln := range unaffected {
 			found := foundVersion(vuln.ModPath, vuln.PkgPath, ci)
-			fixed := fixedVersion(vuln.PkgPath, vuln.OSV.Affected)
+			fixed := fixedVersion(vuln.ModPath, vuln.PkgPath, vuln.OSV.Affected)
 			fmt.Println()
 			writeVulnerability(idx+1, vuln.OSV.ID, vuln.OSV.Details, "", found, fixed, platforms(vuln.OSV))
 		}
@@ -211,15 +211,15 @@
 func foundVersion(modulePath, pkgPath string, ci *callInfo) string {
 	var found string
 	if v := ci.moduleVersions[modulePath]; v != "" {
-		found = packageVersionString(pkgPath, v[1:])
+		found = packageVersionString(modulePath, pkgPath, v[1:])
 	}
 	return found
 }
 
-func fixedVersion(pkgPath string, affected []osv.Affected) string {
+func fixedVersion(modulePath, pkgPath string, affected []osv.Affected) string {
 	fixed := LatestFixed(affected)
 	if fixed != "" {
-		fixed = packageVersionString(pkgPath, fixed)
+		fixed = packageVersionString(modulePath, pkgPath, fixed)
 	}
 	return fixed
 }
@@ -319,9 +319,9 @@
 	return s[:i]
 }
 
-func packageVersionString(packagePath, version string) string {
+func packageVersionString(modulePath, packagePath, version string) string {
 	v := "v" + version
-	if importPathInStdlib(packagePath) {
+	if modulePath == internal.GoStdModulePath {
 		v = semverToGoTag(v)
 	}
 	return fmt.Sprintf("%s@%s", packagePath, v)
diff --git a/internal/govulncheck/stdlib.go b/internal/govulncheck/stdlib.go
index 3edc5d0..8935f3e 100644
--- a/internal/govulncheck/stdlib.go
+++ b/internal/govulncheck/stdlib.go
@@ -69,12 +69,3 @@
 	}
 	return i + 1
 }
-
-// importPathInStdlib reports whether the given import path could be part of the Go standard library,
-// by reporting whether the first component lacks a '.'.
-func importPathInStdlib(path string) bool {
-	if i := strings.IndexByte(path, '/'); i != -1 {
-		path = path[:i]
-	}
-	return !strings.Contains(path, ".")
-}
diff --git a/internal/govulncheck/summary.go b/internal/govulncheck/summary.go
index 0a18ef3..2a6ff63 100644
--- a/internal/govulncheck/summary.go
+++ b/internal/govulncheck/summary.go
@@ -61,7 +61,7 @@
 			PkgPath: v0.PkgPath,
 			ModPath: v0.ModPath,
 			FoundIn: foundVersion(v0.ModPath, v0.PkgPath, ci),
-			FixedIn: fixedVersion(v0.PkgPath, v0.OSV.Affected),
+			FixedIn: fixedVersion(v0.ModPath, v0.PkgPath, v0.OSV.Affected),
 			Trace:   stacks,
 		})
 	}
@@ -71,7 +71,7 @@
 			PkgPath: vuln.PkgPath,
 			ModPath: vuln.ModPath,
 			FoundIn: foundVersion(vuln.ModPath, vuln.PkgPath, ci),
-			FixedIn: fixedVersion(vuln.PkgPath, vuln.OSV.Affected),
+			FixedIn: fixedVersion(vuln.ModPath, vuln.PkgPath, vuln.OSV.Affected),
 		})
 	}
 	return Summary{
diff --git a/internal/internal.go b/internal/internal.go
index dcca07b..8ee8462 100644
--- a/internal/internal.go
+++ b/internal/internal.go
@@ -8,3 +8,18 @@
 // IDDirectory is the name of the directory that contains entries
 // listed by their IDs.
 const IDDirectory = "ID"
+
+// Pseudo-module paths used for parts of the Go system.
+// These are technically not valid module paths, so we
+// mustn't pass them to module.EscapePath.
+// Keep in sync with vulndb/internal/database/generate.go.
+const (
+
+	// GoStdModulePath is the internal Go module path string used
+	// when listing vulnerabilities in standard library.
+	GoStdModulePath = "stdlib"
+
+	// GoCmdModulePath is the internal Go module path string used
+	// when listing vulnerabilities in the go command.
+	GoCmdModulePath = "toolchain"
+)
diff --git a/vulncheck/fetch.go b/vulncheck/fetch.go
index dc0e1c7..2cadd15 100644
--- a/vulncheck/fetch.go
+++ b/vulncheck/fetch.go
@@ -9,10 +9,11 @@
 	"fmt"
 
 	"golang.org/x/vuln/client"
+	"golang.org/x/vuln/internal"
 )
 
 var stdlibModule = &Module{
-	Path: "stdlib",
+	Path: internal.GoStdModulePath,
 	// Version is populated by Source and Binary based on user input
 }