]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/go: allow nested VCS repositories when preparing build stamp
authorJay Conrod <jayconrod@google.com>
Fri, 15 Oct 2021 18:57:58 +0000 (11:57 -0700)
committerJay Conrod <jayconrod@google.com>
Fri, 15 Oct 2021 20:29:36 +0000 (20:29 +0000)
The go command no longer reports an error when invoked in a repository
nested inside another. This check is still used by 'go get' in GOPATH
mode when locating a repository, but it's not needed when preparing
the build stamp.

Fixes #49004

Change-Id: I4ed4dcc04174d2d42da8651d47e52ab1d7d66e35
Reviewed-on: https://go-review.googlesource.com/c/go/+/356309
Trust: Jay Conrod <jayconrod@google.com>
Run-TryBot: Jay Conrod <jayconrod@google.com>
Reviewed-by: Bryan C. Mills <bcmills@google.com>
TryBot-Result: Go Bot <gobot@golang.org>

src/cmd/go/internal/get/get.go
src/cmd/go/internal/load/pkg.go
src/cmd/go/internal/vcs/vcs.go
src/cmd/go/internal/vcs/vcs_test.go
src/cmd/go/testdata/script/version_buildvcs_nested.txt

index c96459297a77bc8497ab1f384d4737e24cecac8b..0412506b9e87531fcac36adb8f84b60dc13abfbf 100644 (file)
@@ -446,7 +446,8 @@ func downloadPackage(p *load.Package) error {
 
        if p.Internal.Build.SrcRoot != "" {
                // Directory exists. Look for checkout along path to src.
-               repoDir, vcsCmd, err = vcs.FromDir(p.Dir, p.Internal.Build.SrcRoot)
+               const allowNesting = false
+               repoDir, vcsCmd, err = vcs.FromDir(p.Dir, p.Internal.Build.SrcRoot, allowNesting)
                if err != nil {
                        return err
                }
index 58dc242383ca03f9a85c481a8fe20765330aab6e..99c4a9c62e339ef0b9d523539b4fcc6045ab7284 100644 (file)
@@ -2318,8 +2318,9 @@ func (p *Package) setBuildInfo() {
        var repoDir string
        var vcsCmd *vcs.Cmd
        var err error
+       const allowNesting = true
        if cfg.BuildBuildvcs && p.Module != nil && p.Module.Version == "" && !p.Standard {
-               repoDir, vcsCmd, err = vcs.FromDir(base.Cwd(), "")
+               repoDir, vcsCmd, err = vcs.FromDir(base.Cwd(), "", allowNesting)
                if err != nil && !errors.Is(err, os.ErrNotExist) {
                        setVCSError(err)
                        return
@@ -2338,7 +2339,7 @@ func (p *Package) setBuildInfo() {
                // repository. vcs.FromDir allows nested Git repositories, but nesting
                // is not allowed for other VCS tools. The current directory may be outside
                // p.Module.Dir when a workspace is used.
-               pkgRepoDir, _, err := vcs.FromDir(p.Dir, "")
+               pkgRepoDir, _, err := vcs.FromDir(p.Dir, "", allowNesting)
                if err != nil {
                        setVCSError(err)
                        return
@@ -2347,7 +2348,7 @@ func (p *Package) setBuildInfo() {
                        setVCSError(fmt.Errorf("main package is in repository %q but current directory is in repository %q", pkgRepoDir, repoDir))
                        return
                }
-               modRepoDir, _, err := vcs.FromDir(p.Module.Dir, "")
+               modRepoDir, _, err := vcs.FromDir(p.Module.Dir, "", allowNesting)
                if err != nil {
                        setVCSError(err)
                        return
index ebb48504434be3f3aeef350f424eefaaa73a5d1b..d1272b66e91dfcb3523971263ec1eb938ae79509 100644 (file)
@@ -603,7 +603,7 @@ type vcsPath struct {
 // version control system and code repository to use.
 // If no repository is found, FromDir returns an error
 // equivalent to os.ErrNotExist.
-func FromDir(dir, srcRoot string) (repoDir string, vcsCmd *Cmd, err error) {
+func FromDir(dir, srcRoot string, allowNesting bool) (repoDir string, vcsCmd *Cmd, err error) {
        // Clean and double-check that dir is in (a subdirectory of) srcRoot.
        dir = filepath.Clean(dir)
        if srcRoot != "" {
@@ -617,11 +617,16 @@ func FromDir(dir, srcRoot string) (repoDir string, vcsCmd *Cmd, err error) {
        for len(dir) > len(srcRoot) {
                for _, vcs := range vcsList {
                        if _, err := os.Stat(filepath.Join(dir, "."+vcs.Cmd)); err == nil {
-                               // Record first VCS we find, but keep looking,
-                               // to detect mistakes like one kind of VCS inside another.
+                               // Record first VCS we find.
+                               // If allowNesting is false (as it is in GOPATH), keep looking for
+                               // repositories in parent directories and report an error if one is
+                               // found to mitigate VCS injection attacks.
                                if vcsCmd == nil {
                                        vcsCmd = vcs
                                        repoDir = dir
+                                       if allowNesting {
+                                               return repoDir, vcsCmd, nil
+                                       }
                                        continue
                                }
                                // Allow .git inside .git, which can arise due to submodules.
index 248c541014ffd8a0291c29c2c3401b1be12635af..9ac0a56a07d5aa30617d488c4937fc62e1bb869e 100644 (file)
@@ -233,7 +233,7 @@ func TestFromDir(t *testing.T) {
                }
 
                wantRepoDir := filepath.Dir(dir)
-               gotRepoDir, gotVCS, err := FromDir(dir, tempDir)
+               gotRepoDir, gotVCS, err := FromDir(dir, tempDir, false)
                if err != nil {
                        t.Errorf("FromDir(%q, %q): %v", dir, tempDir, err)
                        continue
index f904c41bf8fef562db72967cde4ea49397ad620d..08d4c92bafb697ef45f8435cc4e53b75f99b8ad1 100644 (file)
@@ -1,5 +1,6 @@
 [!exec:git] skip
 [!exec:hg] skip
+[short] skip
 env GOFLAGS=-n
 
 # Create a root module in a root Git repository.
@@ -8,25 +9,25 @@ cd root
 go mod init example.com/root
 exec git init
 
-# It's an error to build a package from a nested Mercurial repository
-# without -buildvcs=false, even if the package is in a separate module.
+# Nesting repositories in parent directories are ignored, as the current
+# directory main package, and containing main module are in the same repository.
+# This is an error in GOPATH mode (to prevent VCS injection), but for modules,
+# we assume users have control over repositories they've checked out.
 mkdir hgsub
 cd hgsub
 exec hg init
 cp ../../main.go main.go
 ! go build
-stderr '^error obtaining VCS status: directory ".*hgsub" uses hg, but parent ".*root" uses git$'
-stderr '\tUse -buildvcs=false to disable VCS stamping.$'
-go mod init example.com/root/hgsub
-! go build
-stderr '^error obtaining VCS status: directory ".*hgsub" uses hg, but parent ".*root" uses git$'
+stderr '^error obtaining VCS status: main module is in repository ".*root" but current directory is in repository ".*hgsub"$'
+stderr '^\tUse -buildvcs=false to disable VCS stamping.$'
 go build -buildvcs=false
+go mod init example.com/root/hgsub
+go build
 cd ..
 
 # It's an error to build a package from a nested Git repository if the package
 # is in a separate repository from the current directory or from the module
-# root directory. However, unlike with other VCS, it's okay for a Git repository
-# to be nested within another Git repository. This happens with submodules.
+# root directory.
 mkdir gitsub
 cd gitsub
 exec git init