internal/vulncheck: add warning message for ancient binaries

We emit a warning message for Go binaries built with an ancient Go
version.

Change-Id: I9c7037cb1710181786a7c063ae2a253f880dc6ad
Reviewed-on: https://go-review.googlesource.com/c/vuln/+/597516
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Maceo Thompson <maceothompson@google.com>
diff --git a/cmd/govulncheck/testdata/stdlib/modules/stdlib/old_dont_run_me b/cmd/govulncheck/testdata/stdlib/modules/stdlib/old_dont_run_me
new file mode 100644
index 0000000..2a648cb
--- /dev/null
+++ b/cmd/govulncheck/testdata/stdlib/modules/stdlib/old_dont_run_me
Binary files differ
diff --git a/cmd/govulncheck/testdata/stdlib/testfiles/binary/binary_old_go_text.ct b/cmd/govulncheck/testdata/stdlib/testfiles/binary/binary_old_go_text.ct
new file mode 100644
index 0000000..03aa4df
--- /dev/null
+++ b/cmd/govulncheck/testdata/stdlib/testfiles/binary/binary_old_go_text.ct
@@ -0,0 +1,44 @@
+#####
+# Test verbose scanning with text output for a binary built
+# with an ancient Go version
+$ govulncheck -mode binary -show verbose ${moddir}/stdlib/old_dont_run_me --> FAIL 3
+Scanning your binary for known vulnerabilities...
+
+Fetching vulnerabilities from the database...
+
+Checking the binary against the vulnerabilities...
+
+warning: binary built with Go version go1.12.10, only standard library vulnerabilities will be checked
+
+warning: failed to extract build system specification GOOS:  GOARCH: 
+
+
+=== Symbol Results ===
+
+Vulnerability #1: GO-2022-0969
+    HTTP/2 server connections can hang forever waiting for a clean shutdown that
+    was preempted by a fatal error. This condition can be exploited by a
+    malicious client to cause a denial of service.
+  More info: https://pkg.go.dev/vuln/GO-2022-0969
+  Standard library
+    Found in: net/http@go1.12.10
+    Fixed in: net/http@go1.18.6
+    Vulnerable symbols found:
+      #1: http.ListenAndServe
+      #2: http.ListenAndServeTLS
+      #3: http.Serve
+      #4: http.ServeTLS
+      #5: http.Server.ListenAndServe
+      Use '-show traces' to see the other 4 found symbols
+
+=== Package Results ===
+
+No other vulnerabilities found.
+
+=== Module Results ===
+
+No other vulnerabilities found.
+
+Your code is affected by 1 vulnerability from the Go standard library.
+This scan found no other vulnerabilities in packages you import or modules you
+require.
diff --git a/internal/semver/semver_test.go b/internal/semver/semver_test.go
index e16b26c..4c4a3c8 100644
--- a/internal/semver/semver_test.go
+++ b/internal/semver/semver_test.go
@@ -38,3 +38,22 @@
 		}
 	}
 }
+
+func TestLess(t *testing.T) {
+	for _, test := range []struct {
+		v1   string
+		v2   string
+		want bool
+	}{
+		{"go1.19", "go1.19", false},
+		{"go1.19.1", "go1.19", false},
+		{"v0.2.1", "v0.3.0", true},
+		{"go1.12.2", "go1.18", true},
+		{"v1.20.0-pre4", "v1.20.0-pre.4", false},
+		{"v1.20.0-pre4", "v1.20.0-pre4.4", true},
+	} {
+		if got := Less(test.v1, test.v2); got != test.want {
+			t.Errorf("want Less(%s, %s)=%t; got %t", test.v1, test.v2, test.want, got)
+		}
+	}
+}
diff --git a/internal/vulncheck/binary.go b/internal/vulncheck/binary.go
index db96ba3..03d7a6a 100644
--- a/internal/vulncheck/binary.go
+++ b/internal/vulncheck/binary.go
@@ -13,6 +13,7 @@
 	"golang.org/x/vuln/internal/buildinfo"
 	"golang.org/x/vuln/internal/client"
 	"golang.org/x/vuln/internal/govulncheck"
+	"golang.org/x/vuln/internal/semver"
 )
 
 // Bin is an abstraction of Go binary containing
@@ -64,6 +65,15 @@
 		return nil, err
 	}
 
+	// Emit warning message for ancient Go binaries, defined as binaries
+	// built with Go version without support for debug.BuildInfo (< go1.18).
+	if semver.Less(bin.GoVersion, "go1.18") {
+		p := &govulncheck.Progress{Message: fmt.Sprintf("warning: binary built with Go version %s, only standard library vulnerabilities will be checked", bin.GoVersion)}
+		if err := handler.Progress(p); err != nil {
+			return nil, err
+		}
+	}
+
 	if bin.GOOS == "" || bin.GOARCH == "" {
 		p := &govulncheck.Progress{Message: fmt.Sprintf("warning: failed to extract build system specification GOOS: %s GOARCH: %s\n", bin.GOOS, bin.GOARCH)}
 		if err := handler.Progress(p); err != nil {