diff options
Diffstat (limited to 'src/internal/execabs/execabs.go')
| -rw-r--r-- | src/internal/execabs/execabs.go | 40 |
1 files changed, 37 insertions, 3 deletions
diff --git a/src/internal/execabs/execabs.go b/src/internal/execabs/execabs.go index 5f60fbb119..9a05d971da 100644 --- a/src/internal/execabs/execabs.go +++ b/src/internal/execabs/execabs.go @@ -12,7 +12,11 @@ package execabs import ( "context" + "fmt" "os/exec" + "path/filepath" + "reflect" + "unsafe" ) var ErrNotFound = exec.ErrNotFound @@ -23,14 +27,44 @@ 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) { - return exec.LookPath(file) + 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 = "" + } } func CommandContext(ctx context.Context, name string, arg ...string) *exec.Cmd { - return exec.CommandContext(ctx, name, arg...) + cmd := exec.CommandContext(ctx, name, arg...) + fixCmd(name, cmd) + return cmd + } func Command(name string, arg ...string) *exec.Cmd { - return exec.Command(name, arg...) + cmd := exec.Command(name, arg...) + fixCmd(name, cmd) + return cmd } |
