internal/sarif: add version to module info for locations

This allows makes module information complete so that users can compute
local paths.

Change-Id: I8cedf77908b825d7e66ac9d7a9a075804f207c66
Reviewed-on: https://go-review.googlesource.com/c/vuln/+/581195
Reviewed-by: Ian Cottrell <iancottrell@google.com>
Run-TryBot: Zvonimir Pavlinovic <zpavlinovic@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
diff --git a/cmd/govulncheck/testdata/common/testfiles/binary-call/binary_sarif.ct b/cmd/govulncheck/testdata/common/testfiles/binary-call/binary_sarif.ct
index eaed232..667d19e 100644
--- a/cmd/govulncheck/testdata/common/testfiles/binary-call/binary_sarif.ct
+++ b/cmd/govulncheck/testdata/common/testfiles/binary-call/binary_sarif.ct
@@ -122,7 +122,7 @@
                 {
                   "locations": [
                     {
-                      "module": "github.com/tidwall/gjson",
+                      "module": "github.com/tidwall/gjson@v1.6.5",
                       "location": {
                         "physicalLocation": {
                           "artifactLocation": {},
@@ -148,7 +148,7 @@
               },
               "frames": [
                 {
-                  "module": "github.com/tidwall/gjson",
+                  "module": "github.com/tidwall/gjson@v1.6.5",
                   "location": {
                     "physicalLocation": {
                       "artifactLocation": {},
@@ -175,7 +175,7 @@
                 {
                   "locations": [
                     {
-                      "module": "golang.org/x/text",
+                      "module": "golang.org/x/text@v0.3.0",
                       "location": {
                         "physicalLocation": {
                           "artifactLocation": {},
@@ -201,7 +201,7 @@
               },
               "frames": [
                 {
-                  "module": "golang.org/x/text",
+                  "module": "golang.org/x/text@v0.3.0",
                   "location": {
                     "physicalLocation": {
                       "artifactLocation": {},
@@ -228,7 +228,7 @@
                 {
                   "locations": [
                     {
-                      "module": "github.com/tidwall/gjson",
+                      "module": "github.com/tidwall/gjson@v1.6.5",
                       "location": {
                         "physicalLocation": {
                           "artifactLocation": {},
@@ -251,7 +251,7 @@
                 {
                   "locations": [
                     {
-                      "module": "github.com/tidwall/gjson",
+                      "module": "github.com/tidwall/gjson@v1.6.5",
                       "location": {
                         "physicalLocation": {
                           "artifactLocation": {},
@@ -277,7 +277,7 @@
               },
               "frames": [
                 {
-                  "module": "github.com/tidwall/gjson",
+                  "module": "github.com/tidwall/gjson@v1.6.5",
                   "location": {
                     "physicalLocation": {
                       "artifactLocation": {},
@@ -296,7 +296,7 @@
               },
               "frames": [
                 {
-                  "module": "github.com/tidwall/gjson",
+                  "module": "github.com/tidwall/gjson@v1.6.5",
                   "location": {
                     "physicalLocation": {
                       "artifactLocation": {},
diff --git a/cmd/govulncheck/testdata/common/testfiles/source-call/source_call_sarif.ct b/cmd/govulncheck/testdata/common/testfiles/source-call/source_call_sarif.ct
index 7b6c02e..be6a8e1 100644
--- a/cmd/govulncheck/testdata/common/testfiles/source-call/source_call_sarif.ct
+++ b/cmd/govulncheck/testdata/common/testfiles/source-call/source_call_sarif.ct
@@ -155,7 +155,7 @@
                 {
                   "locations": [
                     {
-                      "module": "golang.org/vuln",
+                      "module": "golang.org/vuln@",
                       "location": {
                         "physicalLocation": {
                           "artifactLocation": {
@@ -173,7 +173,7 @@
                       }
                     },
                     {
-                      "module": "github.com/tidwall/gjson",
+                      "module": "github.com/tidwall/gjson@v1.6.5",
                       "location": {
                         "physicalLocation": {
                           "artifactLocation": {
@@ -191,7 +191,7 @@
                       }
                     },
                     {
-                      "module": "github.com/tidwall/gjson",
+                      "module": "github.com/tidwall/gjson@v1.6.5",
                       "location": {
                         "physicalLocation": {
                           "artifactLocation": {
@@ -209,7 +209,7 @@
                       }
                     },
                     {
-                      "module": "github.com/tidwall/gjson",
+                      "module": "github.com/tidwall/gjson@v1.6.5",
                       "location": {
                         "physicalLocation": {
                           "artifactLocation": {
@@ -241,7 +241,7 @@
               },
               "frames": [
                 {
-                  "module": "golang.org/vuln",
+                  "module": "golang.org/vuln@",
                   "location": {
                     "physicalLocation": {
                       "artifactLocation": {
@@ -259,7 +259,7 @@
                   }
                 },
                 {
-                  "module": "github.com/tidwall/gjson",
+                  "module": "github.com/tidwall/gjson@v1.6.5",
                   "location": {
                     "physicalLocation": {
                       "artifactLocation": {
@@ -277,7 +277,7 @@
                   }
                 },
                 {
-                  "module": "github.com/tidwall/gjson",
+                  "module": "github.com/tidwall/gjson@v1.6.5",
                   "location": {
                     "physicalLocation": {
                       "artifactLocation": {
@@ -295,7 +295,7 @@
                   }
                 },
                 {
-                  "module": "github.com/tidwall/gjson",
+                  "module": "github.com/tidwall/gjson@v1.6.5",
                   "location": {
                     "physicalLocation": {
                       "artifactLocation": {
@@ -313,7 +313,7 @@
                   }
                 },
                 {
-                  "module": "github.com/tidwall/gjson",
+                  "module": "github.com/tidwall/gjson@v1.6.5",
                   "location": {
                     "physicalLocation": {
                       "artifactLocation": {
@@ -331,7 +331,7 @@
                   }
                 },
                 {
-                  "module": "github.com/tidwall/gjson",
+                  "module": "github.com/tidwall/gjson@v1.6.5",
                   "location": {
                     "physicalLocation": {
                       "artifactLocation": {
@@ -380,7 +380,7 @@
                 {
                   "locations": [
                     {
-                      "module": "golang.org/vuln",
+                      "module": "golang.org/vuln@",
                       "location": {
                         "physicalLocation": {
                           "artifactLocation": {
@@ -398,7 +398,7 @@
                       }
                     },
                     {
-                      "module": "golang.org/x/text",
+                      "module": "golang.org/x/text@v0.3.0",
                       "location": {
                         "physicalLocation": {
                           "artifactLocation": {
@@ -430,7 +430,7 @@
               },
               "frames": [
                 {
-                  "module": "golang.org/vuln",
+                  "module": "golang.org/vuln@",
                   "location": {
                     "physicalLocation": {
                       "artifactLocation": {
@@ -448,7 +448,7 @@
                   }
                 },
                 {
-                  "module": "golang.org/x/text",
+                  "module": "golang.org/x/text@v0.3.0",
                   "location": {
                     "physicalLocation": {
                       "artifactLocation": {
@@ -497,7 +497,7 @@
                 {
                   "locations": [
                     {
-                      "module": "golang.org/vuln",
+                      "module": "golang.org/vuln@",
                       "location": {
                         "physicalLocation": {
                           "artifactLocation": {
@@ -515,7 +515,7 @@
                       }
                     },
                     {
-                      "module": "github.com/tidwall/gjson",
+                      "module": "github.com/tidwall/gjson@v1.6.5",
                       "location": {
                         "physicalLocation": {
                           "artifactLocation": {
@@ -547,7 +547,7 @@
               },
               "frames": [
                 {
-                  "module": "golang.org/vuln",
+                  "module": "golang.org/vuln@",
                   "location": {
                     "physicalLocation": {
                       "artifactLocation": {
@@ -565,7 +565,7 @@
                   }
                 },
                 {
-                  "module": "github.com/tidwall/gjson",
+                  "module": "github.com/tidwall/gjson@v1.6.5",
                   "location": {
                     "physicalLocation": {
                       "artifactLocation": {
diff --git a/internal/sarif/handler.go b/internal/sarif/handler.go
index 5cd2656..744e951 100644
--- a/internal/sarif/handler.go
+++ b/internal/sarif/handler.go
@@ -286,7 +286,7 @@
 		}
 
 		sf := Frame{
-			Module:   frame.Module,
+			Module:   frame.Module + "@" + frame.Version,
 			Location: Location{Message: Description{Text: symbol(frame)}}, // show the (full) symbol name
 		}
 		if h.cfg.ScanMode != govulncheck.ScanModeBinary {
@@ -359,7 +359,7 @@
 			}
 
 			tfl := ThreadFlowLocation{
-				Module:   frame.Module,
+				Module:   frame.Module + "@" + frame.Version,
 				Location: Location{Message: Description{Text: symbol(frame)}}, // show the (full) symbol name
 			}
 			if h.cfg.ScanMode != govulncheck.ScanModeBinary {
diff --git a/internal/sarif/sarif.go b/internal/sarif/sarif.go
index ed55640..fb1c5b7 100644
--- a/internal/sarif/sarif.go
+++ b/internal/sarif/sarif.go
@@ -122,6 +122,9 @@
 }
 
 type ThreadFlowLocation struct {
+	// Module is module information in the form <module-path>@<version>.
+	// <version> can be empty when the module version is not known as
+	// with, say, the source module analyzed.
 	Module string `json:"module,omitempty"`
 	// Location also contains a Message field.
 	Location Location `json:"location,omitempty"`
@@ -138,6 +141,9 @@
 // Frame is effectively a module location. It can also contain thread and
 // parameter info, but those are not needed for govulncheck.
 type Frame struct {
+	// Module is module information in the form <module-path>@<version>.
+	// <version> can be empty when the module version is not known as
+	// with, say, the source module analyzed.
 	Module   string   `json:"module,omitempty"`
 	Location Location `json:"location,omitempty"`
 }