From d0146bd85bb6870aa43a498b06ccb473af55cbe3 Mon Sep 17 00:00:00 2001 From: Dmitri Shuralyov Date: Thu, 4 Jul 2024 18:07:45 -0400 Subject: os/exec: only use cachedLookExtensions if Cmd.Path is unmodified Caching the invocation of lookExtensions on an absolute path in Command and reusing the cached result in Start is only viable if Cmd.Path isn't set to a different value after Command returns. For #66586. Fixes #68314. Change-Id: I57007850aca2011b11344180c00faded737617b5 Reviewed-on: https://go-review.googlesource.com/c/go/+/596875 Reviewed-by: qiu laidongfeng2 <2645477756@qq.com> Reviewed-by: Ian Lance Taylor Auto-Submit: Dmitri Shuralyov LUCI-TryBot-Result: Go LUCI Reviewed-by: Dmitri Shuralyov --- src/os/exec/exec_test.go | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) (limited to 'src/os/exec/exec_test.go') diff --git a/src/os/exec/exec_test.go b/src/os/exec/exec_test.go index dbe59fea11..a0bb89e203 100644 --- a/src/os/exec/exec_test.go +++ b/src/os/exec/exec_test.go @@ -1838,7 +1838,7 @@ func TestPathRace(t *testing.T) { func TestAbsPathExec(t *testing.T) { testenv.MustHaveExec(t) - testenv.MustHaveGoBuild(t) // must have GOROOT/bin/gofmt, but close enough + testenv.MustHaveGoBuild(t) // must have GOROOT/bin/{go,gofmt} // A simple exec of a full path should work. // Go 1.22 broke this on Windows, requiring ".exe"; see #66586. @@ -1863,4 +1863,24 @@ func TestAbsPathExec(t *testing.T) { if err == nil { t.Errorf("using exec.Cmd{Path: %#q}: unexpected success", cmd.Path) } + + // A simple exec after modifying Cmd.Path should work. + // This broke on Windows. See go.dev/issue/68314. + t.Run("modified", func(t *testing.T) { + if exec.Command(filepath.Join(testenv.GOROOT(t), "bin/go")).Run() == nil { + // The implementation of the test case below relies on the go binary + // exiting with a non-zero exit code when run without any arguments. + // In the unlikely case that changes, we need to use another binary. + t.Fatal("test case needs updating to verify fix for go.dev/issue/68314") + } + exe1 := filepath.Join(testenv.GOROOT(t), "bin/go") + exe2 := filepath.Join(testenv.GOROOT(t), "bin/gofmt") + cmd := exec.Command(exe1) + cmd.Path = exe2 + cmd.Args = []string{cmd.Path} + err := cmd.Run() + if err != nil { + t.Error("ran wrong binary") + } + }) } -- cgit v1.3