aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/go/internal/modload/load.go
diff options
context:
space:
mode:
authorBryan C. Mills <bcmills@google.com>2020-02-28 15:03:54 -0500
committerBryan C. Mills <bcmills@google.com>2020-02-28 21:56:35 +0000
commit618126b9895db7f29a861caa4e330d149858ff56 (patch)
tree14b22fa6de658827549b6c2e8d6f17bf2d102207 /src/cmd/go/internal/modload/load.go
parent964fac3ee74fe4df5423dad18f78322d88aae84a (diff)
downloadgo-618126b9895db7f29a861caa4e330d149858ff56.tar.gz
go-618126b9895db7f29a861caa4e330d149858ff56.zip
cmd/go: avoid matching wildcards rooted outside of available modules
To avoid confusion, also distinguish between packages and dirs in search.Match results. No test because this is technically only a performance optimization: it would be very difficult to write such a test so that it would not be flaky. (However, tested the change manually.) Fixes #37521 Change-Id: I17b443699ce6a8f3a63805a7ef0be806f695a4b3 Reviewed-on: https://go-review.googlesource.com/c/go/+/221544 Run-TryBot: Bryan C. Mills <bcmills@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Jay Conrod <jayconrod@google.com>
Diffstat (limited to 'src/cmd/go/internal/modload/load.go')
-rw-r--r--src/cmd/go/internal/modload/load.go60
1 files changed, 40 insertions, 20 deletions
diff --git a/src/cmd/go/internal/modload/load.go b/src/cmd/go/internal/modload/load.go
index 32841d96cb..6ea7d8c69b 100644
--- a/src/cmd/go/internal/modload/load.go
+++ b/src/cmd/go/internal/modload/load.go
@@ -65,24 +65,13 @@ func ImportPaths(patterns []string) []*search.Match {
// packages. The build tags should typically be imports.Tags() or
// imports.AnyTags(); a nil map has no special meaning.
func ImportPathsQuiet(patterns []string, tags map[string]bool) []*search.Match {
- var fsDirs [][]string
updateMatches := func(matches []*search.Match, iterating bool) {
- for i, m := range matches {
+ for _, m := range matches {
switch {
case m.IsLocal():
// Evaluate list of file system directories on first iteration.
- if fsDirs == nil {
- fsDirs = make([][]string, len(matches))
- }
- if fsDirs[i] == nil {
- if m.IsLiteral() {
- fsDirs[i] = []string{m.Pattern()}
- } else {
- m.MatchPackagesInFS()
- // Pull out the matching directories: we are going to resolve them
- // to package paths below.
- fsDirs[i], m.Pkgs = m.Pkgs, nil
- }
+ if m.Dirs == nil {
+ matchLocalDirs(m)
}
// Make a copy of the directory list and translate to import paths.
@@ -91,10 +80,9 @@ func ImportPathsQuiet(patterns []string, tags map[string]bool) []*search.Match {
// from not being in the build list to being in it and back as
// the exact version of a particular module increases during
// the loader iterations.
- pkgs := str.StringList(fsDirs[i])
- m.Pkgs = pkgs[:0]
- for _, pkg := range pkgs {
- pkg, err := resolveLocalPackage(pkg)
+ m.Pkgs = m.Pkgs[:0]
+ for _, dir := range m.Dirs {
+ pkg, err := resolveLocalPackage(dir)
if err != nil {
if !m.IsLiteral() && (err == errPkgIsBuiltin || err == errPkgIsGorootSrc) {
continue // Don't include "builtin" or GOROOT/src in wildcard patterns.
@@ -131,7 +119,7 @@ func ImportPathsQuiet(patterns []string, tags map[string]bool) []*search.Match {
}
case m.Pattern() == "std" || m.Pattern() == "cmd":
- if len(m.Pkgs) == 0 {
+ if m.Pkgs == nil {
m.MatchPackages() // Locate the packages within GOROOT/src.
}
@@ -186,6 +174,34 @@ func checkMultiplePaths() {
base.ExitIfErrors()
}
+// matchLocalDirs is like m.MatchDirs, but tries to avoid scanning directories
+// outside of the standard library and active modules.
+func matchLocalDirs(m *search.Match) {
+ if !m.IsLocal() {
+ panic(fmt.Sprintf("internal error: resolveLocalDirs on non-local pattern %s", m.Pattern()))
+ }
+
+ if i := strings.Index(m.Pattern(), "..."); i >= 0 {
+ // The pattern is local, but it is a wildcard. Its packages will
+ // only resolve to paths if they are inside of the standard
+ // library, the main module, or some dependency of the main
+ // module. Verify that before we walk the filesystem: a filesystem
+ // walk in a directory like /var or /etc can be very expensive!
+ dir := filepath.Dir(filepath.Clean(m.Pattern()[:i+3]))
+ absDir := dir
+ if !filepath.IsAbs(dir) {
+ absDir = filepath.Join(base.Cwd, dir)
+ }
+ if search.InDir(absDir, cfg.GOROOTsrc) == "" && search.InDir(absDir, ModRoot()) == "" && pathInModuleCache(absDir) == "" {
+ m.Dirs = []string{}
+ m.AddError(fmt.Errorf("directory prefix %s outside available modules", base.ShortPath(absDir)))
+ return
+ }
+ }
+
+ m.MatchDirs()
+}
+
// resolveLocalPackage resolves a filesystem path to a package path.
func resolveLocalPackage(dir string) (string, error) {
var absDir string
@@ -269,7 +285,11 @@ func resolveLocalPackage(dir string) (string, error) {
}
if sub := search.InDir(absDir, cfg.GOROOTsrc); sub != "" && sub != "." && !strings.Contains(sub, "@") {
- return filepath.ToSlash(sub), nil
+ pkg := filepath.ToSlash(sub)
+ if pkg == "builtin" {
+ return "", errPkgIsBuiltin
+ }
+ return pkg, nil
}
pkg := pathInModuleCache(absDir)