cmd/go/internal/modfetch: avoid bogus hash in go.sum for missing go.mod file

The code inadventently recorded lines in go.sum as if an empty go.mod file
existed when no go.mod file existed at all. This results in many lines in go.sum
for go.mod of non-modules (like misspellings of module paths or packages
within modules).

Stop doing that, and clean up the mess in existing go.sum files.

Change-Id: I9d64810dffd5378c9785566255b39d56eba673e3
Reviewed-on: https://go-review.googlesource.com/122395
Reviewed-by: Bryan C. Mills <bcmills@google.com>
diff --git a/vendor/cmd/go/internal/modfetch/cache.go b/vendor/cmd/go/internal/modfetch/cache.go
index e07b784..be0adc0 100644
--- a/vendor/cmd/go/internal/modfetch/cache.go
+++ b/vendor/cmd/go/internal/modfetch/cache.go
@@ -146,8 +146,8 @@
 		rev = info.Version
 
 		text, err = r.r.GoMod(rev)
-		checkGoMod(r.path, rev, text)
 		if err == nil {
+			checkGoMod(r.path, rev, text)
 			if err := writeDiskGoMod(file, text); err != nil {
 				fmt.Fprintf(os.Stderr, "go: writing go.mod cache: %v\n", err)
 			}
diff --git a/vendor/cmd/go/internal/modfetch/fetch.go b/vendor/cmd/go/internal/modfetch/fetch.go
index df7adda..aff2cc8 100644
--- a/vendor/cmd/go/internal/modfetch/fetch.go
+++ b/vendor/cmd/go/internal/modfetch/fetch.go
@@ -153,6 +153,11 @@
 	return true
 }
 
+// emptyGoModHash is the hash of a 1-file tree containing a 0-length go.mod.
+// A bug caused us to write these into go.sum files for non-modules.
+// We detect and remove them.
+const emptyGoModHash = "h1:G7mAYYxgmS0lVkHyy2hEOLQCFB0DlQFTMLWggykrydY="
+
 // readGoSum parses data, which is the content of file,
 // and adds it to goSum.m. The goSum lock must be held.
 func readGoSum(file string, data []byte) {
@@ -174,6 +179,10 @@
 		if len(f) != 3 {
 			base.Fatalf("go: malformed go.sum:\n%s:%d: wrong number of fields %v", file, lineno, len(f))
 		}
+		if f[2] == emptyGoModHash {
+			// Old bug; drop it.
+			continue
+		}
 		mod := module.Version{Path: f[0], Version: f[1]}
 		goSum.m[mod] = append(goSum.m[mod], f[2])
 	}
diff --git a/vendor/cmd/go/mod_test.go b/vendor/cmd/go/mod_test.go
index 79b4370..565bbb2 100644
--- a/vendor/cmd/go/mod_test.go
+++ b/vendor/cmd/go/mod_test.go
@@ -1019,6 +1019,35 @@
 	tg.run("mod", "-sync") // ignores missing ziphash file for ordinary go.sum validation
 
 	tg.runFail("mod", "-verify") // explicit verify fails with missing ziphash
+
+	tg.run("mod", "-droprequire", "rsc.io/quote")
+	tg.run("list", "rsc.io/quote/buggy")
+	data, err = ioutil.ReadFile(tg.path("x/go.sum"))
+	if strings.Contains(string(data), "buggy") {
+		t.Fatalf("did not expect buggy in go.sum:\n%s", data)
+	}
+	if !strings.Contains(string(data), "rsc.io/quote v1.5.2/go.mod") {
+		t.Fatalf("did expect rsc.io/quote go.mod in go.sum:\n%s", data)
+	}
+
+	tg.run("mod", "-droprequire", "rsc.io/quote")
+	tg.runFail("list", "rsc.io/quote/buggy/foo")
+	data, err = ioutil.ReadFile(tg.path("x/go.sum"))
+	if strings.Contains(string(data), "buggy") {
+		t.Fatalf("did not expect buggy in go.sum:\n%s", data)
+	}
+	if !strings.Contains(string(data), "rsc.io/quote v1.5.2/go.mod") {
+		t.Fatalf("did expect rsc.io/quote go.mod in go.sum:\n%s", data)
+	}
+
+	tg.run("mod", "-droprequire", "rsc.io/quote")
+	tg.runFail("list", "rsc.io/quote/morebuggy")
+	if strings.Contains(string(data), "morebuggy") {
+		t.Fatalf("did not expect morebuggy in go.sum:\n%s", data)
+	}
+	if !strings.Contains(string(data), "rsc.io/quote v1.5.2/go.mod") {
+		t.Fatalf("did expect rsc.io/quote go.mod in go.sum:\n%s", data)
+	}
 }
 
 func TestModVendorNoDeps(t *testing.T) {