Commit b294fe9b authored by Bryan C. Mills's avatar Bryan C. Mills Committed by Russ Cox

cmd/go: prohibit modules from importing vendored golang_org packages

Expand mod_internal tests to cover vendoring, replacements, and failure
messages.

Packages beginning with "golang_org/" resolve to $GOROOT/src/vendor, and should
therefore not be visible within module code.

Fixes #23970.

Change-Id: I706e9c4a1d1e025883e84b897972678d0fa3f2bd
Reviewed-on: https://go-review.googlesource.com/125836
Run-TryBot: Bryan C. Mills <bcmills@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: 's avatarRuss Cox <rsc@golang.org>
parent 68170aa6
...@@ -961,6 +961,8 @@ func disallowInternal(srcDir string, p *Package, stk *ImportStack) *Package { ...@@ -961,6 +961,8 @@ func disallowInternal(srcDir string, p *Package, stk *ImportStack) *Package {
if i > 0 { if i > 0 {
i-- // rewind over slash in ".../internal" i-- // rewind over slash in ".../internal"
} }
var where string
if p.Module == nil { if p.Module == nil {
parent := p.Dir[:i+len(p.Dir)-len(p.ImportPath)] parent := p.Dir[:i+len(p.Dir)-len(p.ImportPath)]
...@@ -978,19 +980,18 @@ func disallowInternal(srcDir string, p *Package, stk *ImportStack) *Package { ...@@ -978,19 +980,18 @@ func disallowInternal(srcDir string, p *Package, stk *ImportStack) *Package {
// p is in a module, so make it available based on the import path instead // p is in a module, so make it available based on the import path instead
// of the file path (https://golang.org/issue/23970). // of the file path (https://golang.org/issue/23970).
parent := p.ImportPath[:i] parent := p.ImportPath[:i]
// TODO(bcmills): In case of replacements, use the module path declared by importer := (*stk)[len(*stk)-2]
// the replacement module, not the path seen by the user. if str.HasPathPrefix(importer, parent) {
importerPath := (*stk)[len(*stk)-2]
if strings.HasPrefix(importerPath, parent) {
return p return p
} }
where = " in " + importer
} }
// Internal is present, and srcDir is outside parent's tree. Not allowed. // Internal is present, and srcDir is outside parent's tree. Not allowed.
perr := *p perr := *p
perr.Error = &PackageError{ perr.Error = &PackageError{
ImportStack: stk.Copy(), ImportStack: stk.Copy(),
Err: "use of internal package " + p.ImportPath + " not allowed", Err: "use of internal package " + p.ImportPath + " not allowed" + where,
} }
perr.Incomplete = true perr.Incomplete = true
return &perr return &perr
...@@ -1027,6 +1028,29 @@ func disallowVendor(srcDir, path string, p *Package, stk *ImportStack) *Package ...@@ -1027,6 +1028,29 @@ func disallowVendor(srcDir, path string, p *Package, stk *ImportStack) *Package
return p return p
} }
if p.Standard && ModPackageModuleInfo != nil {
// Modules must not import vendor packages in the standard library,
// but the usual vendor visibility check will not catch them
// because the module loader presents them with an ImportPath starting
// with "golang_org/" instead of "vendor/".
importer := (*stk)[len(*stk)-2]
if mod := ModPackageModuleInfo(importer); mod != nil {
dir := p.Dir
if relDir, err := filepath.Rel(p.Root, p.Dir); err == nil {
dir = relDir
}
if _, ok := FindVendor(filepath.ToSlash(dir)); ok {
perr := *p
perr.Error = &PackageError{
ImportStack: stk.Copy(),
Err: "use of vendored package " + path + " not allowed",
}
perr.Incomplete = true
return &perr
}
}
}
if perr := disallowVendorVisibility(srcDir, p, stk); perr != p { if perr := disallowVendorVisibility(srcDir, p, stk); perr != p {
return perr return perr
} }
......
env GO111MODULE=on env GO111MODULE=on
# golang.org/x/internal should be importable from other golang.org/x modules. # golang.org/x/internal should be importable from other golang.org/x modules.
rm go.mod
go mod -init -module golang.org/x/anything go mod -init -module golang.org/x/anything
go build . go build .
# ...but that should not leak into other modules. # ...but that should not leak into other modules.
! go build ./baddep ! go build ./baddep
stderr 'use of internal package' stderr 'use of internal package golang.org/x/.* not allowed in golang.org/notx/useinternal$'
# Internal packages in the standard library should not leak into modules. # Internal packages in the standard library should not leak into modules.
! go build ./fromstd ! go build ./fromstd
stderr 'use of internal package' stderr 'use of internal package internal/testenv not allowed$'
# Packages found via standard-library vendoring should not leak.
! go build ./fromstdvendor
stderr 'use of vendored package golang_org/x/net/http/httpguts not allowed$'
# Dependencies should be able to use their own internal modules... # Dependencies should be able to use their own internal modules...
...@@ -20,11 +25,27 @@ go build ./throughdep ...@@ -20,11 +25,27 @@ go build ./throughdep
# ... but other modules should not, even if they have transitive dependencies. # ... but other modules should not, even if they have transitive dependencies.
! go build . ! go build .
stderr 'use of internal package' stderr 'use of internal package golang.org/x/.* not allowed in golang.org/notx$'
# And transitive dependencies still should not leak. # And transitive dependencies still should not leak.
! go build ./baddep ! go build ./baddep
stderr 'use of internal package' stderr 'use of internal package golang.org/x/.* not allowed in golang.org/notx/useinternal$'
# Replacing an internal module should keep it internal to the same paths.
rm go.mod
go mod -init -module golang.org/notx
go mod -replace golang.org/x/internal=./replace/golang.org/notx/internal
go build ./throughdep
! go build ./baddep
stderr 'use of internal package golang.org/x/.* not allowed in golang.org/notx/useinternal$'
go mod -replace golang.org/x/internal=./vendor/golang.org/x/internal
go build ./throughdep
! go build ./baddep
stderr 'use of internal package golang.org/x/.* not allowed in golang.org/notx/useinternal$'
-- useinternal.go -- -- useinternal.go --
...@@ -42,3 +63,21 @@ import _ "golang.org/notx/useinternal" ...@@ -42,3 +63,21 @@ import _ "golang.org/notx/useinternal"
-- fromstd/useinternal.go -- -- fromstd/useinternal.go --
package fromstd package fromstd
import _ "internal/testenv" import _ "internal/testenv"
-- fromstdvendor/useinternal.go --
package fromstdvendor
import _ "golang_org/x/net/http/httpguts"
-- replace/golang.org/notx/internal/go.mod --
module golang.org/x/internal
-- replace/golang.org/notx/internal/subtle/subtle.go --
package subtle
// Ha ha! Nothing here!
-- vendor/golang.org/x/internal/go.mod --
module golang.org/x/internal
-- vendor/golang.org/x/internal/subtle/subtle.go --
package subtle
// Ha ha! Nothing here!
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment