]> Cypherpunks repositories - gostls13.git/commitdiff
all: introduce and use internal/execabs
authorRoland Shoemaker <roland@golang.org>
Fri, 15 Jan 2021 20:14:06 +0000 (12:14 -0800)
committerRoland Shoemaker <roland@golang.org>
Thu, 21 Jan 2021 19:10:18 +0000 (19:10 +0000)
Introduces a wrapper around os/exec, internal/execabs, for use in
all commands. This wrapper prevents exec.LookPath and exec.Command from
running executables in the current directory.

All imports of os/exec in non-test files in cmd/ are replaced with
imports of internal/execabs.

This issue was reported by RyotaK.

Fixes CVE-2021-3115
Fixes #43783

Change-Id: I0423451a6e27ec1e1d6f3fe929ab1ef69145c08f
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/955304
Reviewed-by: Russ Cox <rsc@google.com>
Reviewed-by: Katie Hockman <katiehockman@google.com>
Reviewed-on: https://go-review.googlesource.com/c/go/+/284783
Run-TryBot: Roland Shoemaker <roland@golang.org>
Reviewed-by: Katie Hockman <katie@golang.org>
Trust: Roland Shoemaker <roland@golang.org>

40 files changed:
src/cmd/api/goapi.go
src/cmd/api/run.go
src/cmd/cgo/out.go
src/cmd/cgo/util.go
src/cmd/compile/internal/ssa/html.go
src/cmd/cover/func.go
src/cmd/cover/testdata/toolexec.go
src/cmd/dist/buildtool.go
src/cmd/doc/dirs.go
src/cmd/fix/typecheck.go
src/cmd/go/internal/base/base.go
src/cmd/go/internal/bug/bug.go
src/cmd/go/internal/generate/generate.go
src/cmd/go/internal/modfetch/codehost/codehost.go
src/cmd/go/internal/modfetch/codehost/git.go
src/cmd/go/internal/test/genflags.go
src/cmd/go/internal/test/test.go
src/cmd/go/internal/tool/tool.go
src/cmd/go/internal/vcs/vcs.go
src/cmd/go/internal/vet/vetflag.go
src/cmd/go/internal/work/build.go
src/cmd/go/internal/work/buildid.go
src/cmd/go/internal/work/exec.go
src/cmd/go/internal/work/gccgo.go
src/cmd/go/testdata/addmod.go
src/cmd/internal/browser/browser.go
src/cmd/internal/diff/diff.go
src/cmd/internal/dwarf/dwarf.go
src/cmd/internal/pkgpath/pkgpath.go
src/cmd/link/internal/ld/execarchive.go
src/cmd/link/internal/ld/lib.go
src/cmd/test2json/main.go
src/cmd/trace/pprof.go
src/go/build/build.go
src/go/build/deps_test.go
src/go/internal/gccgoimporter/gccgoinstallation.go
src/go/internal/srcimporter/srcimporter.go
src/internal/execabs/execabs.go [new file with mode: 0644]
src/internal/execabs/execabs_test.go [new file with mode: 0644]
src/internal/goroot/gc.go

index ba42812fa6365e3a1adcf6c20b6606ce5b905820..efc2696f8fecc72bfdf6ad27ffc99ec814cdaae0 100644 (file)
@@ -16,10 +16,10 @@ import (
        "go/parser"
        "go/token"
        "go/types"
+       exec "internal/execabs"
        "io"
        "log"
        "os"
-       "os/exec"
        "path/filepath"
        "regexp"
        "runtime"
index a36f1179c16e9839fa7f1bd417b788a27d9df6db..ecb1d0f81aa46695d47634b94eb6571368e0ffef 100644 (file)
@@ -10,9 +10,9 @@ package main
 
 import (
        "fmt"
+       exec "internal/execabs"
        "log"
        "os"
-       "os/exec"
        "path/filepath"
        "runtime"
        "strings"
index fa6f0efbbe0e20ecf5b6ba8bed7f5229083a8768..8e83f02202f73c15a92b8a1b5fce6f4b18236103 100644 (file)
@@ -14,10 +14,10 @@ import (
        "go/ast"
        "go/printer"
        "go/token"
+       exec "internal/execabs"
        "internal/xcoff"
        "io"
        "os"
-       "os/exec"
        "path/filepath"
        "regexp"
        "sort"
index 779f7be2259b3750166b6edce318adb779e7a3a6..00d931b98a0c1e8416d5bb14334946dbd9a56304 100644 (file)
@@ -8,9 +8,9 @@ import (
        "bytes"
        "fmt"
        "go/token"
+       exec "internal/execabs"
        "io/ioutil"
        "os"
-       "os/exec"
 )
 
 // run runs the command argv, feeding in stdin on standard input.
index a9d52fa4ee056c16d7c3cfc840c71a495f757071..c06b5808e1c00296653f87cfd56a680c4a22c9b4 100644 (file)
@@ -9,9 +9,9 @@ import (
        "cmd/internal/src"
        "fmt"
        "html"
+       exec "internal/execabs"
        "io"
        "os"
-       "os/exec"
        "path/filepath"
        "strconv"
        "strings"
index 988c4caebffe13dc11e6bffb304016abc5673723..ce7c771ac961971af670b00c1c79ea1c8b22153c 100644 (file)
@@ -15,9 +15,9 @@ import (
        "go/ast"
        "go/parser"
        "go/token"
+       exec "internal/execabs"
        "io"
        "os"
-       "os/exec"
        "path"
        "path/filepath"
        "runtime"
index 1769efedbeb678674045a9d6b9bbc08fb4e5ed30..386de79038a355c2de01fead816a1410479490f8 100644 (file)
@@ -16,7 +16,7 @@ package main
 
 import (
        "os"
-       "os/exec"
+       exec "internal/execabs"
        "strings"
 )
 
index e7bedfb84eec506061b2c3a7ba3733b8ac9fbe63..cf85f2ac8ea5ffe408d8d36de8672c554ed40cc1 100644 (file)
@@ -305,8 +305,10 @@ func bootstrapFixImports(srcFile string) string {
                        continue
                }
                if strings.HasPrefix(line, `import "`) || strings.HasPrefix(line, `import . "`) ||
-                       inBlock && (strings.HasPrefix(line, "\t\"") || strings.HasPrefix(line, "\t. \"")) {
+                       inBlock && (strings.HasPrefix(line, "\t\"") || strings.HasPrefix(line, "\t. \"") || strings.HasPrefix(line, "\texec \"")) {
                        line = strings.Replace(line, `"cmd/`, `"bootstrap/cmd/`, -1)
+                       // During bootstrap, must use plain os/exec.
+                       line = strings.Replace(line, `exec "internal/execabs"`, `"os/exec"`, -1)
                        for _, dir := range bootstrapDirs {
                                if strings.HasPrefix(dir, "cmd/") {
                                        continue
index 38cbe7fa021973943c459461684f14b58220b7be..661624cfe4c168c793d582203de163f3169634e6 100644 (file)
@@ -7,9 +7,9 @@ package main
 import (
        "bytes"
        "fmt"
+       exec "internal/execabs"
        "log"
        "os"
-       "os/exec"
        "path/filepath"
        "regexp"
        "strings"
index 40b2287f26e9c9ce9dda9adae2afd8ed7a3293cf..39a53785b724d4105ccfd6d7bdd320a7f3428005 100644 (file)
@@ -9,8 +9,8 @@ import (
        "go/ast"
        "go/parser"
        "go/token"
+       exec "internal/execabs"
        "os"
-       "os/exec"
        "path/filepath"
        "reflect"
        "runtime"
index 004588c73204d6054c667e4949fbca94a641a4ac..954ce47a9899325014b4e99b5b6a1875a4120f30 100644 (file)
@@ -10,9 +10,9 @@ import (
        "context"
        "flag"
        "fmt"
+       exec "internal/execabs"
        "log"
        "os"
-       "os/exec"
        "strings"
        "sync"
 
index 1085feaaee83b44c60542f73720d2fd1a8ed5d47..4aa08b4ff6ea7ab988daa86f3243b12948f0b64f 100644 (file)
@@ -9,10 +9,10 @@ import (
        "bytes"
        "context"
        "fmt"
+       exec "internal/execabs"
        "io"
        urlpkg "net/url"
        "os"
-       "os/exec"
        "path/filepath"
        "regexp"
        "runtime"
index b1e001c8008ba5f852185d67925726f8453da728..a48311d51b09b7a2a356e1e567abfcaa1af60b7b 100644 (file)
@@ -12,10 +12,10 @@ import (
        "fmt"
        "go/parser"
        "go/token"
+       exec "internal/execabs"
        "io"
        "log"
        "os"
-       "os/exec"
        "path/filepath"
        "regexp"
        "strconv"
index 86c1c14d4a7ad643f5fd30d0aae095ad878b7da1..378fbae34f9530378ced67a8298f797891af9e72 100644 (file)
@@ -10,10 +10,10 @@ import (
        "bytes"
        "crypto/sha256"
        "fmt"
+       exec "internal/execabs"
        "io"
        "io/fs"
        "os"
-       "os/exec"
        "path/filepath"
        "strings"
        "sync"
index 8abc039e7fc0688a1b002a34f95109182bdef0a1..72005e27d5eb83e75d56053dae51e64eb8ea63c8 100644 (file)
@@ -8,11 +8,11 @@ import (
        "bytes"
        "errors"
        "fmt"
+       exec "internal/execabs"
        "io"
        "io/fs"
        "net/url"
        "os"
-       "os/exec"
        "path/filepath"
        "sort"
        "strconv"
index 5e83d53980c01741b950329c53266c3eca4ba9fd..30334b0f305ce495cc0475a43f6c08da063c90be 100644 (file)
@@ -9,9 +9,9 @@ package main
 import (
        "bytes"
        "flag"
+       exec "internal/execabs"
        "log"
        "os"
-       "os/exec"
        "strings"
        "testing"
        "text/template"
index 50fe2dbf393b1f89bdaa484cc8a63e5b690ffef5..7fc9e8fbdcda1afb5837d5b2932329890b49b6a2 100644 (file)
@@ -11,10 +11,10 @@ import (
        "errors"
        "fmt"
        "go/build"
+       exec "internal/execabs"
        "io"
        "io/fs"
        "os"
-       "os/exec"
        "path"
        "path/filepath"
        "regexp"
index 6a755bc43627874a3f789ba4dc7467e12b146c59..95c90ea7c8da4a3f5121af3d78db4b80d8b18f65 100644 (file)
@@ -8,8 +8,8 @@ package tool
 import (
        "context"
        "fmt"
+       exec "internal/execabs"
        "os"
-       "os/exec"
        "os/signal"
        "sort"
        "strings"
index 327ea7cc86327de9e1f1518553793fea2b43c0ef..9feffe07656e84fa7fc821e5b52250d85077bedf 100644 (file)
@@ -8,13 +8,13 @@ import (
        "encoding/json"
        "errors"
        "fmt"
+       exec "internal/execabs"
        "internal/lazyregexp"
        "internal/singleflight"
        "io/fs"
        "log"
        urlpkg "net/url"
        "os"
-       "os/exec"
        "path/filepath"
        "regexp"
        "strings"
index ef995ef83539a1f2e7017fd12b3bbd6384abcb81..5bf5cf44467f144f27df7a267203c9745e1645e5 100644 (file)
@@ -10,9 +10,9 @@ import (
        "errors"
        "flag"
        "fmt"
+       exec "internal/execabs"
        "log"
        "os"
-       "os/exec"
        "path/filepath"
        "strings"
 
index 873d85de4e646e101bb36acabe3fc64d825f13d5..780d639c5d9f3e16cdc8e6b1bfbbc34245145617 100644 (file)
@@ -9,9 +9,9 @@ import (
        "errors"
        "fmt"
        "go/build"
+       exec "internal/execabs"
        "internal/goroot"
        "os"
-       "os/exec"
        "path"
        "path/filepath"
        "runtime"
index d76988145bedc780d61375ee9a3f3d60f5c99756..c555d4a9f1ed036367fbfc0a0ed4d4e748919e09 100644 (file)
@@ -7,8 +7,8 @@ package work
 import (
        "bytes"
        "fmt"
+       exec "internal/execabs"
        "os"
-       "os/exec"
        "strings"
 
        "cmd/go/internal/base"
index e7509042667409aff9fa5e210109bef6ddadd696..16a4ebaa0f78c02a1bfb89d7a5f1563cbd224332 100644 (file)
@@ -13,13 +13,13 @@ import (
        "encoding/json"
        "errors"
        "fmt"
+       exec "internal/execabs"
        "internal/lazyregexp"
        "io"
        "io/fs"
        "log"
        "math/rand"
        "os"
-       "os/exec"
        "path/filepath"
        "regexp"
        "runtime"
index 45ff7c983837084c1387ca40f9f9877eda579046..b58c8aa8854a459a53f5226a322eee342af296ab 100644 (file)
@@ -6,8 +6,8 @@ package work
 
 import (
        "fmt"
+       exec "internal/execabs"
        "os"
-       "os/exec"
        "path/filepath"
        "strings"
        "sync"
index 58376b7ed4ace8df006bba91e703b210f42bf5e6..09fc8e713bcbcfbc9ad226567369df1f2387d446 100644 (file)
@@ -25,7 +25,7 @@ import (
        "io/fs"
        "log"
        "os"
-       "os/exec"
+       exec "internal/execabs"
        "path/filepath"
        "strings"
 
index 6867c85d2320406bb4c80b8960f5b958c6a2f196..577d31789f19afcb768e847cd69d2714e4d48b06 100644 (file)
@@ -6,8 +6,8 @@
 package browser
 
 import (
+       exec "internal/execabs"
        "os"
-       "os/exec"
        "runtime"
        "time"
 )
index e9d2c237800a9c6c658eb41db1b58dcff102fe18..c0ca2f310630cd7266a770d6b42748ae034cb050 100644 (file)
@@ -7,9 +7,9 @@
 package diff
 
 import (
+       exec "internal/execabs"
        "io/ioutil"
        "os"
-       "os/exec"
        "runtime"
 )
 
index e1a70ef853e7c06d53d306f18e167f78e0b4bfcd..8de4096f068ea6fa60b655f5458686f11d765579 100644 (file)
@@ -12,7 +12,7 @@ import (
        "cmd/internal/objabi"
        "errors"
        "fmt"
-       "os/exec"
+       exec "internal/execabs"
        "sort"
        "strconv"
        "strings"
index 40a040a81af6acb54eb272d7bf388b8f79289d99..72e3bdb6311611c4ce645e21c642f45efc847a76 100644 (file)
@@ -10,9 +10,9 @@ import (
        "bytes"
        "errors"
        "fmt"
+       exec "internal/execabs"
        "io/ioutil"
        "os"
-       "os/exec"
        "strings"
 )
 
index fe5cc4086573b4b7754ec604f6e64c09e6a7b3e2..4687c624de464611e7de9036ae187c3e94be6023 100644 (file)
@@ -7,8 +7,8 @@
 package ld
 
 import (
+       exec "internal/execabs"
        "os"
-       "os/exec"
        "path/filepath"
        "syscall"
 )
index 014969664b42214adafcd83cf7f2e25f1c32a91c..17d5040827c0e4b03f708b719bf7752c486f3cf6 100644 (file)
@@ -49,11 +49,11 @@ import (
        "encoding/base64"
        "encoding/binary"
        "fmt"
+       exec "internal/execabs"
        "io"
        "io/ioutil"
        "log"
        "os"
-       "os/exec"
        "path/filepath"
        "runtime"
        "sort"
index e40881ab3fc1ebe73e2769db5551b54e2383277e..fdf681a8ffe564cc07715b7c218b789345446d27 100644 (file)
@@ -86,9 +86,9 @@ package main
 import (
        "flag"
        "fmt"
+       exec "internal/execabs"
        "io"
        "os"
-       "os/exec"
 
        "cmd/internal/test2json"
 )
index a73ff5336afab0ced026cb58775a40c4184eeeaf..c4d37428209ab61d7cc74f44725bc93a421a7dcf 100644 (file)
@@ -9,11 +9,11 @@ package main
 import (
        "bufio"
        "fmt"
+       exec "internal/execabs"
        "internal/trace"
        "io"
        "net/http"
        "os"
-       "os/exec"
        "path/filepath"
        "runtime"
        "sort"
index 72311c7d2c0e636e4b23b533e779dd3ee6ab56f6..217fadf5bd48600402cd310192d735c7731d9037 100644 (file)
@@ -11,13 +11,13 @@ import (
        "go/ast"
        "go/doc"
        "go/token"
+       exec "internal/execabs"
        "internal/goroot"
        "internal/goversion"
        "io"
        "io/fs"
        "io/ioutil"
        "os"
-       "os/exec"
        pathpkg "path"
        "path/filepath"
        "runtime"
index 99cd59e5b5cb907eb9cf04fa6f4a69fad7b8a49e..c97c668cc4922914c12008c4c53f0ebd8321fb14 100644 (file)
@@ -178,7 +178,7 @@ var depsRules = `
        reflect !< OS;
 
        OS
-       < golang.org/x/sys/cpu, internal/goroot;
+       < golang.org/x/sys/cpu;
 
        # FMT is OS (which includes string routines) plus reflect and fmt.
        # It does not include package log, which should be avoided in core packages.
@@ -194,6 +194,12 @@ var depsRules = `
 
        log !< FMT;
 
+       OS, FMT
+       < internal/execabs;
+
+       OS, internal/execabs
+       < internal/goroot;
+
        # Misc packages needing only FMT.
        FMT
        < flag,
index 8fc7ce3232190c93bb74f445bf55be1929e4c786..e90a3cc0b0a343e601bc2fe6389e43a160c713b9 100644 (file)
@@ -7,8 +7,8 @@ package gccgoimporter
 import (
        "bufio"
        "go/types"
+       exec "internal/execabs"
        "os"
-       "os/exec"
        "path/filepath"
        "strings"
 )
index c4d501dcd91bbd6629eaae9cc84345af7b777bf0..438ae0ff2ee7de290df6510ebb5edcf7539ab243 100644 (file)
@@ -13,9 +13,9 @@ import (
        "go/parser"
        "go/token"
        "go/types"
+       exec "internal/execabs"
        "io"
        "os"
-       "os/exec"
        "path/filepath"
        "strings"
        "sync"
diff --git a/src/internal/execabs/execabs.go b/src/internal/execabs/execabs.go
new file mode 100644 (file)
index 0000000..9a05d97
--- /dev/null
@@ -0,0 +1,70 @@
+// Copyright 2021 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 is a drop-in replacement for os/exec
+// that requires PATH lookups to find absolute paths.
+// That is, execabs.Command("cmd") runs the same PATH lookup
+// as exec.Command("cmd"), but if the result is a path
+// which is relative, the Run and Start methods will report
+// an error instead of running the executable.
+package execabs
+
+import (
+       "context"
+       "fmt"
+       "os/exec"
+       "path/filepath"
+       "reflect"
+       "unsafe"
+)
+
+var ErrNotFound = exec.ErrNotFound
+
+type (
+       Cmd       = exec.Cmd
+       Error     = exec.Error
+       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 = ""
+       }
+}
+
+func CommandContext(ctx context.Context, name string, arg ...string) *exec.Cmd {
+       cmd := exec.CommandContext(ctx, name, arg...)
+       fixCmd(name, cmd)
+       return cmd
+
+}
+
+func Command(name string, arg ...string) *exec.Cmd {
+       cmd := exec.Command(name, arg...)
+       fixCmd(name, cmd)
+       return cmd
+}
diff --git a/src/internal/execabs/execabs_test.go b/src/internal/execabs/execabs_test.go
new file mode 100644 (file)
index 0000000..b714585
--- /dev/null
@@ -0,0 +1,104 @@
+// 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"
+       "io/ioutil"
+       "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 := ioutil.WriteFile(filepath.Join(tmpDir, executable), []byte{1, 2, 3}, 0111); err != nil {
+                       t.Fatalf("ioutil.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 := ioutil.WriteFile(filepath.Join(tmpDir, executable), []byte{1, 2, 3}, 0111); err != nil {
+               t.Fatalf("ioutil.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())
+       }
+}
index 0f541d734b0418e54ffcf9200180a4969bb42c7d..ce72bc389656a43681504ee97feff50b60526f1a 100644 (file)
@@ -7,8 +7,8 @@
 package goroot
 
 import (
+       exec "internal/execabs"
        "os"
-       "os/exec"
        "path/filepath"
        "strings"
        "sync"