diff options
| author | Bryan C. Mills <bcmills@google.com> | 2022-06-24 15:36:25 -0400 |
|---|---|---|
| committer | Bryan Mills <bcmills@google.com> | 2022-06-28 19:29:51 +0000 |
| commit | 3580ef9d64bdc0176cde032d170737a6e67ef8f2 (patch) | |
| tree | b8ac2d1a7f02597afe0b60504cd4a3d62484cd55 /src/os/exec/lp_windows.go | |
| parent | 34f3ac5f165d50356d3a8940dc87b77e9b2b7fb9 (diff) | |
| download | go-3580ef9d64bdc0176cde032d170737a6e67ef8f2.tar.xz | |
os/exec: on Windows, suppress ErrDot if the implicit path matches the explicit one
If the current directory is also listed explicitly in %PATH%,
this changes the behavior of LookPath to prefer the explicit name for it
(and thereby avoid ErrDot).
However, in order to avoid running a different executable from what
would have been run by previous Go versions, we still return the
implicit path (and ErrDot) if it refers to a different file entirely.
Fixes #53536.
Updates #43724.
Change-Id: I7ab01074e21a0e8b07a176e3bc6d3b8cf0c873cd
Reviewed-on: https://go-review.googlesource.com/c/go/+/414054
Reviewed-by: Russ Cox <rsc@golang.org>
Run-TryBot: Bryan Mills <bcmills@google.com>
Reviewed-by: Ian Lance Taylor <iant@google.com>
Reviewed-by: Alex Brainman <alex.brainman@gmail.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Diffstat (limited to 'src/os/exec/lp_windows.go')
| -rw-r--r-- | src/os/exec/lp_windows.go | 25 |
1 files changed, 24 insertions, 1 deletions
diff --git a/src/os/exec/lp_windows.go b/src/os/exec/lp_windows.go index dab5770298..da047585eb 100644 --- a/src/os/exec/lp_windows.go +++ b/src/os/exec/lp_windows.go @@ -96,20 +96,43 @@ func LookPath(file string) (string, error) { // have configured their environment this way! // https://docs.microsoft.com/en-us/windows/win32/api/processenv/nf-processenv-needcurrentdirectoryforexepathw // See also go.dev/issue/43947. + var ( + dotf string + dotErr error + ) if _, found := syscall.Getenv("NoDefaultCurrentDirectoryInExePath"); !found { if f, err := findExecutable(filepath.Join(".", file), exts); err == nil { - return f, &Error{file, ErrDot} + dotf, dotErr = f, &Error{file, ErrDot} } } path := os.Getenv("path") for _, dir := range filepath.SplitList(path) { if f, err := findExecutable(filepath.Join(dir, file), exts); err == nil { + if dotErr != nil { + // https://go.dev/issue/53536: if we resolved a relative path implicitly, + // and it is the same executable that would be resolved from the explicit %PATH%, + // prefer the explicit name for the executable (and, likely, no error) instead + // of the equivalent implicit name with ErrDot. + // + // Otherwise, return the ErrDot for the implicit path as soon as we find + // out that the explicit one doesn't match. + dotfi, dotfiErr := os.Lstat(dotf) + fi, fiErr := os.Lstat(f) + if dotfiErr != nil || fiErr != nil || !os.SameFile(dotfi, fi) { + return dotf, dotErr + } + } + if !filepath.IsAbs(f) { return f, &Error{file, ErrDot} } return f, nil } } + + if dotErr != nil { + return dotf, dotErr + } return "", &Error{file, ErrNotFound} } |
