]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/go/internal/base: in AppendPWD, check that PWD is absolute
authorBryan C. Mills <bcmills@google.com>
Wed, 12 Jan 2022 18:28:33 +0000 (13:28 -0500)
committerBryan Mills <bcmills@google.com>
Wed, 20 Apr 2022 14:09:12 +0000 (14:09 +0000)
The POSIX standard requires the PWD variable to be an absolute path.

Fixes #46832

Change-Id: I1938592538633e1a0a0958276f1fefc3c4808399
Reviewed-on: https://go-review.googlesource.com/c/go/+/378396
Run-TryBot: Bryan Mills <bcmills@google.com>
Reviewed-by: Michael Matloob <matloob@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>

src/cmd/go/internal/base/env.go
src/cmd/go/internal/generate/generate_test.go
src/cmd/go/internal/vcs/vcs.go
src/cmd/go/internal/work/buildid.go
src/cmd/go/internal/work/exec.go
src/cmd/go/testdata/script/mod_list_direct.txt

index 5f2665d2367082bc20dbfa586be7571b14536c0b..2f47300f2ec80087826fa2bf40ce4c0b02aac48e 100644 (file)
@@ -4,12 +4,20 @@
 
 package base
 
+import (
+       "fmt"
+       "path/filepath"
+)
+
 // AppendPWD returns the result of appending PWD=dir to the environment base.
 //
 // The resulting environment makes os.Getwd more efficient for a subprocess
 // running in dir.
 func AppendPWD(base []string, dir string) []string {
-       // Internally we only use absolute paths, so dir is absolute.
-       // Even if dir is not absolute, no harm done.
+       // POSIX requires PWD to be absolute.
+       // Internally we only use absolute paths, so dir should already be absolute.
+       if !filepath.IsAbs(dir) {
+               panic(fmt.Sprintf("AppendPWD with relative path %q", dir))
+       }
        return append(base, "PWD="+dir)
 }
index 15b1279f36bd7887f543bdd708990aebec7f137f..d61ecf104a1ec569dc5143993552cbdd52eb788f 100644 (file)
@@ -5,7 +5,9 @@
 package generate
 
 import (
+       "internal/testenv"
        "os"
+       "path/filepath"
        "reflect"
        "runtime"
        "testing"
@@ -41,10 +43,11 @@ var splitTests = []splitTest{
 }
 
 func TestGenerateCommandParse(t *testing.T) {
+       dir := filepath.Join(testenv.GOROOT(t), "src", "sys")
        g := &Generator{
                r:        nil, // Unused here.
-               path:     "/usr/ken/sys/proc.go",
-               dir:      "/usr/ken/sys",
+               path:     filepath.Join(dir, "proc.go"),
+               dir:      dir,
                file:     "proc.go",
                pkg:      "sys",
                commands: make(map[string][]string),
@@ -84,10 +87,11 @@ var defEnvMap = map[string]string{
 //     before executing the test.  i.e., execute the split as if it
 //     processing that source line.
 func TestGenerateCommandShorthand(t *testing.T) {
+       dir := filepath.Join(testenv.GOROOT(t), "src", "sys")
        g := &Generator{
                r:        nil, // Unused here.
-               path:     "/usr/ken/sys/proc.go",
-               dir:      "/usr/ken/sys",
+               path:     filepath.Join(dir, "proc.go"),
+               dir:      dir,
                file:     "proc.go",
                pkg:      "sys",
                commands: make(map[string][]string),
@@ -222,10 +226,11 @@ var splitTestsLines = []splitTestWithLine{
 //     before executing the test.  i.e., execute the split as if it
 //     processing that source line.
 func TestGenerateCommandShortHand2(t *testing.T) {
+       dir := filepath.Join(testenv.GOROOT(t), "src", "sys")
        g := &Generator{
                r:        nil, // Unused here.
-               path:     "/usr/ken/sys/proc.go",
-               dir:      "/usr/ken/sys",
+               path:     filepath.Join(dir, "proc.go"),
+               dir:      dir,
                file:     "proc.go",
                pkg:      "sys",
                commands: make(map[string][]string),
index 2acabf7aafba5de9c33eb3469399afefd2595b22..77208ab7626749d1c2e79f04592e6a8fd70d736c 100644 (file)
@@ -669,7 +669,7 @@ func (v *Cmd) run1(dir string, cmdline string, keyval []string, verbose bool) ([
                        if ee, ok := err.(*exec.ExitError); ok && len(ee.Stderr) > 0 {
                                os.Stderr.Write(ee.Stderr)
                        } else {
-                               fmt.Fprintf(os.Stderr, err.Error())
+                               fmt.Fprintln(os.Stderr, err.Error())
                        }
                }
        }
@@ -678,14 +678,24 @@ func (v *Cmd) run1(dir string, cmdline string, keyval []string, verbose bool) ([
 
 // Ping pings to determine scheme to use.
 func (v *Cmd) Ping(scheme, repo string) error {
-       return v.runVerboseOnly(".", v.PingCmd, "scheme", scheme, "repo", repo)
+       // Run the ping command in an arbitrary working directory,
+       // but don't let the current working directory pollute the results.
+       // In module mode, we expect GOMODCACHE to exist and be a safe place for
+       // commands; in GOPATH mode, we expect that to be true of GOPATH/src.
+       dir := cfg.GOMODCACHE
+       if !cfg.ModulesEnabled {
+               dir = filepath.Join(cfg.BuildContext.GOPATH, "src")
+       }
+       os.MkdirAll(dir, 0777) // Ignore errors — if unsuccessful, the command will likely fail.
+
+       return v.runVerboseOnly(dir, v.PingCmd, "scheme", scheme, "repo", repo)
 }
 
 // Create creates a new copy of repo in dir.
 // The parent of dir must exist; dir must not.
 func (v *Cmd) Create(dir, repo string) error {
        for _, cmd := range v.CreateCmd {
-               if err := v.run(".", cmd, "dir", dir, "repo", repo); err != nil {
+               if err := v.run(filepath.Dir(dir), cmd, "dir", dir, "repo", repo); err != nil {
                        return err
                }
        }
index 76335e9bb170b145d71ff15de5d5383090b2db17..ac98aa344c8bfc2647f3c479864318c04d0597e9 100644 (file)
@@ -160,7 +160,6 @@ func (b *Builder) toolID(name string) string {
 
        cmdline := str.StringList(cfg.BuildToolexec, path, "-V=full")
        cmd := exec.Command(cmdline[0], cmdline[1:]...)
-       cmd.Env = base.AppendPWD(os.Environ(), cmd.Dir)
        var stdout, stderr bytes.Buffer
        cmd.Stdout = &stdout
        cmd.Stderr = &stderr
@@ -219,9 +218,8 @@ func (b *Builder) gccToolID(name, language string) (string, error) {
        // compile an empty file on standard input.
        cmdline := str.StringList(cfg.BuildToolexec, name, "-###", "-x", language, "-c", "-")
        cmd := exec.Command(cmdline[0], cmdline[1:]...)
-       cmd.Env = base.AppendPWD(os.Environ(), cmd.Dir)
        // Force untranslated output so that we see the string "version".
-       cmd.Env = append(cmd.Env, "LC_ALL=C")
+       cmd.Env = append(os.Environ(), "LC_ALL=C")
        out, err := cmd.CombinedOutput()
        if err != nil {
                return "", fmt.Errorf("%s: %v; output: %q", name, err, out)
index 9c9d58b2a178d2f4ae070455fca44fd493c02d01..f0e6c800298f3d47d439504cb47a76e9c18a1c69 100644 (file)
@@ -2116,8 +2116,11 @@ func (b *Builder) runOut(a *Action, dir string, env []string, cmdargs ...any) ([
        cmd.Stderr = &buf
        cleanup := passLongArgsInResponseFiles(cmd)
        defer cleanup()
-       cmd.Dir = dir
-       cmd.Env = base.AppendPWD(os.Environ(), cmd.Dir)
+       cmd.Env = os.Environ()
+       if dir != "." {
+               cmd.Dir = dir
+               cmd.Env = base.AppendPWD(cmd.Env, dir)
+       }
 
        // Add the TOOLEXEC_IMPORTPATH environment variable for -toolexec tools.
        // It doesn't really matter if -toolexec isn't being used.
@@ -3071,7 +3074,7 @@ var (
 )
 
 func (b *Builder) swigDoVersionCheck() error {
-       out, err := b.runOut(nil, "", nil, "swig", "-version")
+       out, err := b.runOut(nil, ".", nil, "swig", "-version")
        if err != nil {
                return err
        }
index 9b7a04c5044302b4aaac7fb5b24fb6738e6bf014..3aa1881554edcec6768fa985f81e7b4169a3f7a8 100644 (file)
@@ -10,7 +10,7 @@ env GOSUMDB=off
 # For a while, (*modfetch.codeRepo).Stat was not checking for a go.mod file,
 # which would produce a hard error at the subsequent call to GoMod.
 
-go get
+go get -v
 
 -- go.mod --
 module example.com