]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/go/internal/modload: set errors for packages with invalid import paths
authorBryan C. Mills <bcmills@google.com>
Wed, 16 Feb 2022 17:33:17 +0000 (12:33 -0500)
committerBryan Mills <bcmills@google.com>
Wed, 16 Feb 2022 19:10:58 +0000 (19:10 +0000)
Prior to CL 339170, relative errors in module mode resulted in a
base.Fatalf from the module loader, which caused unrecoverable errors
from 'go list -e' but successfully rejected relative imports (which
were never intended to work in module mode in the first place).

After that CL, the base.Fatalf is no longer present, but some errors
that had triggered that base.Fatalf were no longer diagnosed at all:
the module loader left them for the package loader to report, and the
package loader assumed that the module loader would report them.

Since the module loader already knows that the paths are invalid,
it now reports those errors itself.

Fixes #51125

Change-Id: I70e5818cfcfeea0ac70e17274427b08a74fd7c13
Reviewed-on: https://go-review.googlesource.com/c/go/+/386176
Trust: Bryan Mills <bcmills@google.com>
Run-TryBot: Bryan Mills <bcmills@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Russ Cox <rsc@golang.org>
src/cmd/compile/internal/test/testdata/ptrsort.go
src/cmd/go/internal/load/pkg.go
src/cmd/go/internal/modload/import.go
src/cmd/go/internal/modload/load.go
src/cmd/go/testdata/script/build_internal.txt
src/cmd/go/testdata/script/run_issue51125.txt [new file with mode: 0644]
src/cmd/go/testdata/script/test_relative_cmdline.txt

index 6cc7ba4851bba39fef93918ed78aa76d2fb17397..d26ba581d91dd9092e122542980643e601f03a99 100644 (file)
@@ -6,7 +6,7 @@ package main
 import (
        "fmt"
 
-       "./mysort"
+       "cmd/compile/internal/test/testdata/mysort"
 )
 
 type MyString struct {
index 214502da7cd06cd23fe9c01190eb60b1f436d250..d68f43a7c9846849937cc23954f49d4a8149f973 100644 (file)
@@ -819,11 +819,11 @@ func loadPackageData(ctx context.Context, path, parentPath, parentDir, parentRoo
        }
        r := resolvedImportCache.Do(importKey, func() any {
                var r resolvedImport
-               if build.IsLocalImport(path) {
+               if cfg.ModulesEnabled {
+                       r.dir, r.path, r.err = modload.Lookup(parentPath, parentIsStd, path)
+               } else if build.IsLocalImport(path) {
                        r.dir = filepath.Join(parentDir, path)
                        r.path = dirToImportPath(r.dir)
-               } else if cfg.ModulesEnabled {
-                       r.dir, r.path, r.err = modload.Lookup(parentPath, parentIsStd, path)
                } else if mode&ResolveImport != 0 {
                        // We do our own path resolution, because we want to
                        // find out the key to use in packageCache without the
@@ -1113,6 +1113,7 @@ func dirAndRoot(path string, dir, root string) (string, string) {
        }
 
        if !str.HasFilePathPrefix(dir, root) || len(dir) <= len(root) || dir[len(root)] != filepath.Separator || path != "command-line-arguments" && !build.IsLocalImport(path) && filepath.Join(root, path) != dir {
+               debug.PrintStack()
                base.Fatalf("unexpected directory layout:\n"+
                        "       import path: %s\n"+
                        "       root: %s\n"+
index 812e48a1568f16e62ac33f07a90f8e4d9d8595e7..4862f625b48ed99a9158f7a8fe3feaa5936139f9 100644 (file)
@@ -248,12 +248,26 @@ func (e *invalidImportError) Unwrap() error {
 // return the module, its root directory, and a list of other modules that
 // lexically could have provided the package but did not.
 func importFromModules(ctx context.Context, path string, rs *Requirements, mg *ModuleGraph) (m module.Version, dir string, altMods []module.Version, err error) {
+       invalidf := func(format string, args ...interface{}) (module.Version, string, []module.Version, error) {
+               return module.Version{}, "", nil, &invalidImportError{
+                       importPath: path,
+                       err:        fmt.Errorf(format, args...),
+               }
+       }
+
        if strings.Contains(path, "@") {
-               return module.Version{}, "", nil, fmt.Errorf("import path should not have @version")
+               return invalidf("import path %q should not have @version", path)
        }
        if build.IsLocalImport(path) {
-               return module.Version{}, "", nil, fmt.Errorf("relative import not supported")
+               return invalidf("%q is relative, but relative import paths are not supported in module mode", path)
        }
+       if filepath.IsAbs(path) {
+               return invalidf("%q is not a package path; see 'go help packages'", path)
+       }
+       if search.IsMetaPackage(path) {
+               return invalidf("%q is not an importable package; see 'go help packages'", path)
+       }
+
        if path == "C" {
                // There's no directory for import "C".
                return module.Version{}, "", nil, nil
index a4a7cb263eb70834f2941e4afa06a11534877a57..d4847efb9880b0365af3e5374692333d5b105043 100644 (file)
@@ -1675,24 +1675,6 @@ func (ld *loader) preloadRootModules(ctx context.Context, rootPkgs []string) (ch
 
 // load loads an individual package.
 func (ld *loader) load(ctx context.Context, pkg *loadPkg) {
-       if strings.Contains(pkg.path, "@") {
-               // Leave for error during load.
-               return
-       }
-       if build.IsLocalImport(pkg.path) || filepath.IsAbs(pkg.path) {
-               // Leave for error during load.
-               // (Module mode does not allow local imports.)
-               return
-       }
-
-       if search.IsMetaPackage(pkg.path) {
-               pkg.err = &invalidImportError{
-                       importPath: pkg.path,
-                       err:        fmt.Errorf("%q is not an importable package; see 'go help packages'", pkg.path),
-               }
-               return
-       }
-
        var mg *ModuleGraph
        if ld.requirements.pruning == unpruned {
                var err error
index 25aa18cfcb33c0bb5dd8d2874b5777a733d2275d..5b786f2fbce509d86ebac1515ce5845db6ef2aef 100644 (file)
@@ -10,8 +10,10 @@ stderr 'internal'
 
 # Test internal packages outside GOROOT are respected
 cd ../testinternal2
+env GO111MODULE=off
 ! go build -v .
 stderr 'p\.go:3:8: use of internal package .*internal/w not allowed'
+env GO111MODULE=''
 
 [gccgo] skip # gccgo does not have GOROOT
 cd ../testinternal
diff --git a/src/cmd/go/testdata/script/run_issue51125.txt b/src/cmd/go/testdata/script/run_issue51125.txt
new file mode 100644 (file)
index 0000000..8fa4486
--- /dev/null
@@ -0,0 +1,54 @@
+# Regression test for https://go.dev/issue/51125:
+# Relative import paths (a holdover from GOPATH) were accidentally allowed in module mode.
+
+cd $WORK
+
+# Relative imports should not be allowed with a go.mod file.
+
+! go run driver.go
+stderr '^driver.go:3:8: "./mypkg" is relative, but relative import paths are not supported in module mode$'
+
+go list -e -f '{{with .Error}}{{.}}{{end}}' -deps driver.go
+stdout '^driver.go:3:8: "./mypkg" is relative, but relative import paths are not supported in module mode$'
+! stderr .
+
+
+# Relative imports should not be allowed in module mode even without a go.mod file.
+rm go.mod
+
+! go run driver.go
+stderr '^driver.go:3:8: "./mypkg" is relative, but relative import paths are not supported in module mode$'
+
+go list -e -f '{{with .Error}}{{.}}{{end}}' -deps driver.go
+stdout '^driver.go:3:8: "./mypkg" is relative, but relative import paths are not supported in module mode$'
+! stderr .
+
+
+# In GOPATH mode, they're still allowed (but only outside of GOPATH/src).
+env GO111MODULE=off
+
+[!short] go run driver.go
+
+go list -deps driver.go
+
+
+-- $WORK/go.mod --
+module example
+
+go 1.17
+-- $WORK/driver.go --
+package main
+
+import "./mypkg"
+
+func main() {
+       mypkg.MyFunc()
+}
+-- $WORK/mypkg/code.go --
+package mypkg
+
+import "fmt"
+
+func MyFunc() {
+       fmt.Println("Hello, world!")
+}
index 2f9c80fe4d5d8d43c1e6304a5fb2a8da19e7e0ce..96f7b872652b236379de4ca7ecf920b12d4a66eb 100644 (file)
@@ -1,5 +1,7 @@
 # Relative imports in command line package
 
+env GO111MODULE=off
+
 # Run tests outside GOPATH.
 env GOPATH=$WORK/tmp
 
@@ -47,4 +49,4 @@ func TestF1(t *testing.T) {
        if F() != p2.F() {
                t.Fatal(F())
        }
-}
\ No newline at end of file
+}