1
0
mirror of https://github.com/golang/go synced 2024-11-26 04:07:59 -07:00

cmd: upgrade golang.org/x/mod to relax import path check

This incorporates CL 297089, which allows leading dots in import path
elements but not module path elements. Also added a test.

Fixes #43985
Updates #34992

Change-Id: I2d5faabd8f7b23a7943d3f3ccb6707ab5dc2ce3c
Reviewed-on: https://go-review.googlesource.com/c/go/+/297530
Trust: Jay Conrod <jayconrod@google.com>
Run-TryBot: Jay Conrod <jayconrod@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Bryan C. Mills <bcmills@google.com>
This commit is contained in:
Jay Conrod 2021-03-01 10:00:09 -05:00
parent f6a74c6568
commit 97bdac03ae
6 changed files with 82 additions and 20 deletions

View File

@ -6,7 +6,7 @@ require (
github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2
golang.org/x/arch v0.0.0-20201008161808-52c3e6f60cff
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897
golang.org/x/mod v0.4.2-0.20210225160341-66bf157bf5bc
golang.org/x/mod v0.4.2-0.20210301144719-c8bb1bd8a2aa
golang.org/x/sys v0.0.0-20210218145245-beda7e5e158e // indirect
golang.org/x/tools v0.1.1-0.20210220032852-2363391a5b2f
)

View File

@ -14,8 +14,8 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897 h1:pLI5jrR7OSLijeIDcmRxNmw2api+jEfxLoykJVice/E=
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2-0.20210225160341-66bf157bf5bc h1:xQukuh0OD2SNSUK1CCBFATgHYx5ye75S/bAWEU/PT0E=
golang.org/x/mod v0.4.2-0.20210225160341-66bf157bf5bc/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2-0.20210301144719-c8bb1bd8a2aa h1:Ci2bbuyE4ah9djFByg+fdNQcqc8DVSdcXbrWy6MBoEs=
golang.org/x/mod v0.4.2-0.20210301144719-c8bb1bd8a2aa/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=

View File

@ -431,7 +431,7 @@ func downloadPackage(p *load.Package) error {
}
importPrefix = importPrefix[:slash]
}
if err := module.CheckImportPath(importPrefix); err != nil {
if err := checkImportPath(importPrefix); err != nil {
return fmt.Errorf("%s: invalid import path: %v", p.ImportPath, err)
}
security := web.SecureOnly
@ -591,3 +591,31 @@ func selectTag(goVersion string, tags []string) (match string) {
}
return ""
}
// checkImportPath is like module.CheckImportPath, but it forbids leading dots
// in path elements. This can lead to 'go get' creating .git and other VCS
// directories in places we might run VCS tools later.
func checkImportPath(path string) error {
if err := module.CheckImportPath(path); err != nil {
return err
}
checkElem := func(elem string) error {
if elem[0] == '.' {
return fmt.Errorf("malformed import path %q: leading dot in path element", path)
}
return nil
}
elemStart := 0
for i, r := range path {
if r == '/' {
if err := checkElem(path[elemStart:]); err != nil {
return err
}
elemStart = i + 1
}
}
if err := checkElem(path[elemStart:]); err != nil {
return err
}
return nil
}

View File

@ -23,6 +23,20 @@ cd $WORK/gopath/src/badname
! go list .
stderr 'invalid module path'
# Test that an import path containing an element with a leading dot is valid,
# but such a module path is not.
# Verifies #43985.
cd $WORK/gopath/src/dotname
go list ./.dot
stdout '^example.com/dotname/.dot$'
go list ./use
stdout '^example.com/dotname/use$'
! go list -m example.com/dotname/.dot@latest
stderr '^go list -m: example.com/dotname/.dot@latest: malformed module path "example.com/dotname/.dot": leading dot in path element$'
go get -d example.com/dotname/.dot
go get -d example.com/dotname/use
go mod tidy
-- mod/go.mod --
-- mod/foo.go --
@ -38,3 +52,13 @@ module .\.
-- badname/foo.go --
package badname
-- dotname/go.mod --
module example.com/dotname
go 1.16
-- dotname/.dot/dot.go --
package dot
-- dotname/use/use.go --
package use
import _ "example.com/dotname/.dot"

View File

@ -270,7 +270,7 @@ func fileNameOK(r rune) bool {
// CheckPath checks that a module path is valid.
// A valid module path is a valid import path, as checked by CheckImportPath,
// with two additional constraints.
// with three additional constraints.
// First, the leading path element (up to the first slash, if any),
// by convention a domain name, must contain only lower-case ASCII letters,
// ASCII digits, dots (U+002E), and dashes (U+002D);
@ -280,8 +280,9 @@ func fileNameOK(r rune) bool {
// and must not contain any dots. For paths beginning with "gopkg.in/",
// this second requirement is replaced by a requirement that the path
// follow the gopkg.in server's conventions.
// Third, no path element may begin with a dot.
func CheckPath(path string) error {
if err := checkPath(path, false); err != nil {
if err := checkPath(path, modulePath); err != nil {
return fmt.Errorf("malformed module path %q: %v", path, err)
}
i := strings.Index(path, "/")
@ -315,7 +316,7 @@ func CheckPath(path string) error {
//
// A valid path element is a non-empty string made up of
// ASCII letters, ASCII digits, and limited ASCII punctuation: - . _ and ~.
// It must not begin or end with a dot (U+002E), nor contain two dots in a row.
// It must not end with a dot (U+002E), nor contain two dots in a row.
//
// The element prefix up to the first dot must not be a reserved file name
// on Windows, regardless of case (CON, com1, NuL, and so on). The element
@ -326,19 +327,29 @@ func CheckPath(path string) error {
// top-level package documentation for additional information about
// subtleties of Unicode.
func CheckImportPath(path string) error {
if err := checkPath(path, false); err != nil {
if err := checkPath(path, importPath); err != nil {
return fmt.Errorf("malformed import path %q: %v", path, err)
}
return nil
}
// pathKind indicates what kind of path we're checking. Module paths,
// import paths, and file paths have different restrictions.
type pathKind int
const (
modulePath pathKind = iota
importPath
filePath
)
// checkPath checks that a general path is valid.
// It returns an error describing why but not mentioning path.
// Because these checks apply to both module paths and import paths,
// the caller is expected to add the "malformed ___ path %q: " prefix.
// fileName indicates whether the final element of the path is a file name
// (as opposed to a directory name).
func checkPath(path string, fileName bool) error {
func checkPath(path string, kind pathKind) error {
if !utf8.ValidString(path) {
return fmt.Errorf("invalid UTF-8")
}
@ -357,35 +368,34 @@ func checkPath(path string, fileName bool) error {
elemStart := 0
for i, r := range path {
if r == '/' {
if err := checkElem(path[elemStart:i], fileName); err != nil {
if err := checkElem(path[elemStart:i], kind); err != nil {
return err
}
elemStart = i + 1
}
}
if err := checkElem(path[elemStart:], fileName); err != nil {
if err := checkElem(path[elemStart:], kind); err != nil {
return err
}
return nil
}
// checkElem checks whether an individual path element is valid.
// fileName indicates whether the element is a file name (not a directory name).
func checkElem(elem string, fileName bool) error {
func checkElem(elem string, kind pathKind) error {
if elem == "" {
return fmt.Errorf("empty path element")
}
if strings.Count(elem, ".") == len(elem) {
return fmt.Errorf("invalid path element %q", elem)
}
if elem[0] == '.' && !fileName {
if elem[0] == '.' && kind == modulePath {
return fmt.Errorf("leading dot in path element")
}
if elem[len(elem)-1] == '.' {
return fmt.Errorf("trailing dot in path element")
}
charOK := pathOK
if fileName {
if kind == filePath {
charOK = fileNameOK
}
for _, r := range elem {
@ -406,7 +416,7 @@ func checkElem(elem string, fileName bool) error {
}
}
if fileName {
if kind == filePath {
// don't check for Windows short-names in file names. They're
// only an issue for import paths.
return nil
@ -444,7 +454,7 @@ func checkElem(elem string, fileName bool) error {
// top-level package documentation for additional information about
// subtleties of Unicode.
func CheckFilePath(path string) error {
if err := checkPath(path, true); err != nil {
if err := checkPath(path, filePath); err != nil {
return fmt.Errorf("malformed file path %q: %v", path, err)
}
return nil
@ -647,7 +657,7 @@ func EscapePath(path string) (escaped string, err error) {
// Versions are allowed to be in non-semver form but must be valid file names
// and not contain exclamation marks.
func EscapeVersion(v string) (escaped string, err error) {
if err := checkElem(v, true); err != nil || strings.Contains(v, "!") {
if err := checkElem(v, filePath); err != nil || strings.Contains(v, "!") {
return "", &InvalidVersionError{
Version: v,
Err: fmt.Errorf("disallowed version string"),
@ -706,7 +716,7 @@ func UnescapeVersion(escaped string) (v string, err error) {
if !ok {
return "", fmt.Errorf("invalid escaped version %q", escaped)
}
if err := checkElem(v, true); err != nil {
if err := checkElem(v, filePath); err != nil {
return "", fmt.Errorf("invalid escaped version %q: %v", v, err)
}
return v, nil

View File

@ -28,7 +28,7 @@ golang.org/x/arch/x86/x86asm
golang.org/x/crypto/ed25519
golang.org/x/crypto/ed25519/internal/edwards25519
golang.org/x/crypto/ssh/terminal
# golang.org/x/mod v0.4.2-0.20210225160341-66bf157bf5bc
# golang.org/x/mod v0.4.2-0.20210301144719-c8bb1bd8a2aa
## explicit
golang.org/x/mod/internal/lazyregexp
golang.org/x/mod/modfile