aboutsummaryrefslogtreecommitdiff
path: root/src/internal/execabs
diff options
context:
space:
mode:
authorRuss Cox <rsc@golang.org>2022-01-27 12:59:37 -0500
committerRuss Cox <rsc@golang.org>2022-04-29 20:16:31 +0000
commit3ce203db80cd1f320f0c597123b918c3b3bb0449 (patch)
treeb04d8b6179ea82e08f5e39837fb77739f7dc3b35 /src/internal/execabs
parent8c5917cd76905b1ab16d41eadc8786e190eeecce (diff)
downloadgo-3ce203db80cd1f320f0c597123b918c3b3bb0449.tar.xz
os/exec: return error when PATH lookup would use current directory
Following discussion on #43724, change os/exec to take the approach of golang.org/x/sys/execabs, refusing to respect path entries mentioning relative paths by default. Code that insists on being able to find executables in relative directories in the path will need to add a couple lines to override the error. See the updated package docs in exec.go for more details. Fixes #43724. Fixes #43947. Change-Id: I73c1214f322b60b4167a23e956e933d50470fe13 Reviewed-on: https://go-review.googlesource.com/c/go/+/381374 Reviewed-by: Bryan Mills <bcmills@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Run-TryBot: Bryan Mills <bcmills@google.com>
Diffstat (limited to 'src/internal/execabs')
-rw-r--r--src/internal/execabs/execabs.go40
-rw-r--r--src/internal/execabs/execabs_test.go103
2 files changed, 3 insertions, 140 deletions
diff --git a/src/internal/execabs/execabs.go b/src/internal/execabs/execabs.go
index 9a05d971da..5f60fbb119 100644
--- a/src/internal/execabs/execabs.go
+++ b/src/internal/execabs/execabs.go
@@ -12,11 +12,7 @@ package execabs
import (
"context"
- "fmt"
"os/exec"
- "path/filepath"
- "reflect"
- "unsafe"
)
var ErrNotFound = exec.ErrNotFound
@@ -27,44 +23,14 @@ type (
ExitError = exec.ExitError
)
-func relError(file, path string) error {
- return fmt.Errorf("%s resolves to executable relative to current directory (.%c%s)", file, filepath.Separator, path)
-}
-
func LookPath(file string) (string, error) {
- path, err := exec.LookPath(file)
- if err != nil {
- return "", err
- }
- if filepath.Base(file) == file && !filepath.IsAbs(path) {
- return "", relError(file, path)
- }
- return path, nil
-}
-
-func fixCmd(name string, cmd *exec.Cmd) {
- if filepath.Base(name) == name && !filepath.IsAbs(cmd.Path) {
- // exec.Command was called with a bare binary name and
- // exec.LookPath returned a path which is not absolute.
- // Set cmd.lookPathErr and clear cmd.Path so that it
- // cannot be run.
- lookPathErr := (*error)(unsafe.Pointer(reflect.ValueOf(cmd).Elem().FieldByName("lookPathErr").Addr().Pointer()))
- if *lookPathErr == nil {
- *lookPathErr = relError(name, cmd.Path)
- }
- cmd.Path = ""
- }
+ return exec.LookPath(file)
}
func CommandContext(ctx context.Context, name string, arg ...string) *exec.Cmd {
- cmd := exec.CommandContext(ctx, name, arg...)
- fixCmd(name, cmd)
- return cmd
-
+ return exec.CommandContext(ctx, name, arg...)
}
func Command(name string, arg ...string) *exec.Cmd {
- cmd := exec.Command(name, arg...)
- fixCmd(name, cmd)
- return cmd
+ return exec.Command(name, arg...)
}
diff --git a/src/internal/execabs/execabs_test.go b/src/internal/execabs/execabs_test.go
deleted file mode 100644
index 97a3f39b4a..0000000000
--- a/src/internal/execabs/execabs_test.go
+++ /dev/null
@@ -1,103 +0,0 @@
-// Copyright 2020 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package execabs
-
-import (
- "context"
- "fmt"
- "internal/testenv"
- "os"
- "os/exec"
- "path/filepath"
- "runtime"
- "testing"
-)
-
-func TestFixCmd(t *testing.T) {
- cmd := &exec.Cmd{Path: "hello"}
- fixCmd("hello", cmd)
- if cmd.Path != "" {
- t.Error("fixCmd didn't clear cmd.Path")
- }
- expectedErr := fmt.Sprintf("hello resolves to executable relative to current directory (.%chello)", filepath.Separator)
- if err := cmd.Run(); err == nil {
- t.Fatal("Command.Run didn't fail")
- } else if err.Error() != expectedErr {
- t.Fatalf("Command.Run returned unexpected error: want %q, got %q", expectedErr, err.Error())
- }
-}
-
-func TestCommand(t *testing.T) {
- testenv.MustHaveExec(t)
-
- for _, cmd := range []func(string) *Cmd{
- func(s string) *Cmd { return Command(s) },
- func(s string) *Cmd { return CommandContext(context.Background(), s) },
- } {
- tmpDir := t.TempDir()
- executable := "execabs-test"
- if runtime.GOOS == "windows" {
- executable += ".exe"
- }
- if err := os.WriteFile(filepath.Join(tmpDir, executable), []byte{1, 2, 3}, 0111); err != nil {
- t.Fatalf("os.WriteFile failed: %s", err)
- }
- cwd, err := os.Getwd()
- if err != nil {
- t.Fatalf("os.Getwd failed: %s", err)
- }
- defer os.Chdir(cwd)
- if err = os.Chdir(tmpDir); err != nil {
- t.Fatalf("os.Chdir failed: %s", err)
- }
- if runtime.GOOS != "windows" {
- // add "." to PATH so that exec.LookPath looks in the current directory on
- // non-windows platforms as well
- origPath := os.Getenv("PATH")
- defer os.Setenv("PATH", origPath)
- os.Setenv("PATH", fmt.Sprintf(".:%s", origPath))
- }
- expectedErr := fmt.Sprintf("execabs-test resolves to executable relative to current directory (.%c%s)", filepath.Separator, executable)
- if err = cmd("execabs-test").Run(); err == nil {
- t.Fatalf("Command.Run didn't fail when exec.LookPath returned a relative path")
- } else if err.Error() != expectedErr {
- t.Errorf("Command.Run returned unexpected error: want %q, got %q", expectedErr, err.Error())
- }
- }
-}
-
-func TestLookPath(t *testing.T) {
- testenv.MustHaveExec(t)
-
- tmpDir := t.TempDir()
- executable := "execabs-test"
- if runtime.GOOS == "windows" {
- executable += ".exe"
- }
- if err := os.WriteFile(filepath.Join(tmpDir, executable), []byte{1, 2, 3}, 0111); err != nil {
- t.Fatalf("os.WriteFile failed: %s", err)
- }
- cwd, err := os.Getwd()
- if err != nil {
- t.Fatalf("os.Getwd failed: %s", err)
- }
- defer os.Chdir(cwd)
- if err = os.Chdir(tmpDir); err != nil {
- t.Fatalf("os.Chdir failed: %s", err)
- }
- if runtime.GOOS != "windows" {
- // add "." to PATH so that exec.LookPath looks in the current directory on
- // non-windows platforms as well
- origPath := os.Getenv("PATH")
- defer os.Setenv("PATH", origPath)
- os.Setenv("PATH", fmt.Sprintf(".:%s", origPath))
- }
- expectedErr := fmt.Sprintf("execabs-test resolves to executable relative to current directory (.%c%s)", filepath.Separator, executable)
- if _, err := LookPath("execabs-test"); err == nil {
- t.Fatalf("LookPath didn't fail when finding a non-relative path")
- } else if err.Error() != expectedErr {
- t.Errorf("LookPath returned unexpected error: want %q, got %q", expectedErr, err.Error())
- }
-}