From c0ee2fd4e309ef0b8f4ab6f4860e2626c8e00802 Mon Sep 17 00:00:00 2001 From: Michael Matloob Date: Tue, 29 Jul 2025 14:17:33 -0400 Subject: [PATCH] cmd/go: explicitly reject module paths "go" and "toolchain" The module paths "go" and "toolchain" are reserved for the dependency on the go and toolchain versions. Check for those paths in go mod init to create modules, go mod edit, and in the module loader and return an error when attempting to use those paths for a work module. Trying to init or load a work module with a go.mod that specifies the module path "go" panics since Go 1.21 (when the toolchain switching logic and the implicit dependencies on the "go" module was introduced), and this change returns a proper error instead of panicking. Fixes #74784 Change-Id: I10e712f8fddbea63edaeb37e14c6d783722e623f Reviewed-on: https://go-review.googlesource.com/c/go/+/691515 Reviewed-by: Ian Alexander LUCI-TryBot-Result: Go LUCI Reviewed-by: Michael Matloob --- src/cmd/go/internal/modcmd/edit.go | 6 ++++- src/cmd/go/internal/modload/init.go | 12 +++++++++ src/cmd/go/internal/modload/modfile.go | 2 ++ .../testdata/script/mod_init_issue74784.txt | 26 +++++++++++++++++++ 4 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 src/cmd/go/testdata/script/mod_init_issue74784.txt diff --git a/src/cmd/go/internal/modcmd/edit.go b/src/cmd/go/internal/modcmd/edit.go index f73269378a..aafd9752a8 100644 --- a/src/cmd/go/internal/modcmd/edit.go +++ b/src/cmd/go/internal/modcmd/edit.go @@ -234,7 +234,11 @@ func runEdit(ctx context.Context, cmd *base.Command, args []string) { } if *editModule != "" { - if err := module.CheckImportPath(*editModule); err != nil { + err := module.CheckImportPath(*editModule) + if err == nil { + err = modload.CheckReservedModulePath(*editModule) + } + if err != nil { base.Fatalf("go: invalid -module: %v", err) } } diff --git a/src/cmd/go/internal/modload/init.go b/src/cmd/go/internal/modload/init.go index 3cf447e648..e537fddfcd 100644 --- a/src/cmd/go/internal/modload/init.go +++ b/src/cmd/go/internal/modload/init.go @@ -1122,6 +1122,16 @@ func errWorkTooOld(gomod string, wf *modfile.WorkFile, goVers string) error { base.ShortPath(filepath.Dir(gomod)), goVers, verb, gover.FromGoWork(wf)) } +// CheckReservedModulePath checks whether the module path is a reserved module path +// that can't be used for a user's module. +func CheckReservedModulePath(path string) error { + if gover.IsToolchain(path) { + return errors.New("module path is reserved") + } + + return nil +} + // CreateModFile initializes a new module by creating a go.mod file. // // If modPath is empty, CreateModFile will attempt to infer the path from the @@ -1156,6 +1166,8 @@ func CreateModFile(ctx context.Context, modPath string) { } } base.Fatal(err) + } else if err := CheckReservedModulePath(modPath); err != nil { + base.Fatalf(`go: invalid module path %q: `, modPath) } else if _, _, ok := module.SplitPathVersion(modPath); !ok { if strings.HasPrefix(modPath, "gopkg.in/") { invalidMajorVersionMsg := fmt.Errorf("module paths beginning with gopkg.in/ must always have a major version suffix in the form of .vN:\n\tgo mod init %s", suggestGopkgIn(modPath)) diff --git a/src/cmd/go/internal/modload/modfile.go b/src/cmd/go/internal/modload/modfile.go index cb385c3505..04e204cc98 100644 --- a/src/cmd/go/internal/modload/modfile.go +++ b/src/cmd/go/internal/modload/modfile.go @@ -68,6 +68,8 @@ func ReadModFile(gomod string, fix modfile.VersionFixer) (data []byte, f *modfil if f.Module == nil { // No module declaration. Must add module path. return nil, nil, fmt.Errorf("error reading %s: missing module declaration. To specify the module path:\n\tgo mod edit -module=example.com/mod", base.ShortPath(gomod)) + } else if err := CheckReservedModulePath(f.Module.Mod.Path); err != nil { + return nil, nil, fmt.Errorf("error reading %s: invalid module path: %q", base.ShortPath(gomod), f.Module.Mod.Path) } return data, f, err diff --git a/src/cmd/go/testdata/script/mod_init_issue74784.txt b/src/cmd/go/testdata/script/mod_init_issue74784.txt new file mode 100644 index 0000000000..f7863636e5 --- /dev/null +++ b/src/cmd/go/testdata/script/mod_init_issue74784.txt @@ -0,0 +1,26 @@ +# Don't allow the creation of modules with special "go" or "toolchain" paths. +! go mod init go +! stderr 'panic' +stderr 'invalid module path' + +! go mod init toolchain +! stderr 'panic' +stderr 'invalid module path' + +# A module that contains the path element "go" is okay. +go mod init example.com/go +stderr 'creating new go.mod' + +# go mod edit won't allow a reserved module path either +! go mod edit -module=go +stderr 'invalid -module' + +# The go command should check for work modules for bad +# names to return a proper error and avoid a panic. +cp badmod.txt go.mod +! go list +! stderr panic +stderr 'invalid module path' + +-- badmod.txt -- +module go -- 2.51.0