x/vgo: filter non-canonical sevmer tags from repos

Accepting abbreviated semver tags from repositories was
re-considered to be harmful.

Fixes golang/go#24476.

Change-Id: I03b4731ce4bcf376fb04f472e2fcf7f4de456178
Reviewed-on: https://go-review.googlesource.com/104855
Run-TryBot: Russ Cox <rsc@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Russ Cox <rsc@golang.org>
diff --git a/vendor/cmd/go/internal/modfetch/coderepo.go b/vendor/cmd/go/internal/modfetch/coderepo.go
index 5f51abe..22e640b 100644
--- a/vendor/cmd/go/internal/modfetch/coderepo.go
+++ b/vendor/cmd/go/internal/modfetch/coderepo.go
@@ -88,6 +88,10 @@
 		if r.codeDir != "" {
 			v = v[len(r.codeDir)+1:]
 		}
+		// Only accept canonical semver tags from the repo. (See #24476.)
+		if v != semver.Canonical(v) {
+			continue
+		}
 		if !module.MatchPathMajor(v, r.pathMajor) {
 			continue
 		}
diff --git a/vendor/cmd/go/internal/modfetch/coderepo_test.go b/vendor/cmd/go/internal/modfetch/coderepo_test.go
index ac203ea..e23a575 100644
--- a/vendor/cmd/go/internal/modfetch/coderepo_test.go
+++ b/vendor/cmd/go/internal/modfetch/coderepo_test.go
@@ -6,7 +6,9 @@
 
 import (
 	"archive/zip"
+	"cmd/go/internal/modfetch/codehost"
 	"cmd/go/internal/webtest"
+	"io"
 	"io/ioutil"
 	"os"
 	"reflect"
@@ -600,3 +602,46 @@
 		})
 	}
 }
+
+// fixedTagsRepo is a fake codehost.Repo that returns a fixed list of tags
+type fixedTagsRepo struct {
+	root string
+	tags []string
+}
+
+func (ch *fixedTagsRepo) Tags(string) ([]string, error)                         { return ch.tags, nil }
+func (ch *fixedTagsRepo) Root() string                                          { return ch.root }
+func (ch *fixedTagsRepo) LatestAt(time.Time, string) (*codehost.RevInfo, error) { panic("not impl") }
+func (ch *fixedTagsRepo) ReadFile(string, string, int64) ([]byte, error)        { panic("not impl") }
+func (ch *fixedTagsRepo) ReadZip(string, string, int64) (io.ReadCloser, string, error) {
+	panic("not impl")
+}
+func (ch *fixedTagsRepo) Stat(string) (*codehost.RevInfo, error) { panic("not impl") }
+
+func TestNonCanonicalSemver(t *testing.T) {
+	root := "golang.org/x/issue24476"
+	ch := &fixedTagsRepo{
+		root: root,
+		tags: []string{
+			"", "huh?", "1.0.1",
+			// what about "version 1 dot dogcow"?
+			"v1.🐕.🐄",
+			"v1", "v0.1",
+			// and one normal one that should pass through
+			"v1.0.1",
+		},
+	}
+
+	cr, err := newCodeRepo(ch, root)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	v, err := cr.Versions("")
+	if err != nil {
+		t.Fatal(err)
+	}
+	if len(v) != 1 || v[0] != "v1.0.1" {
+		t.Fatal("unexpected versions returned:", v)
+	}
+}