diff options
| author | Olivier Mengué <olivier.mengue@gmail.com> | 2025-06-30 16:58:59 +0200 |
|---|---|---|
| committer | Gopher Robot <gobot@golang.org> | 2025-07-29 13:53:57 -0700 |
| commit | e0b07dc22eaab1b003d98ad6d63cdfacc76c5c70 (patch) | |
| tree | 429d9eb4a4432b27d24dd57e91c774d12f87fffd /src/os/exec/dot_test.go | |
| parent | 25816d401c459a9dfedded3b42315a8bd2d32802 (diff) | |
| download | go-e0b07dc22eaab1b003d98ad6d63cdfacc76c5c70.tar.xz | |
os/exec: fix incorrect expansion of "", "." and ".." in LookPath
Fix incorrect expansion of "" and "." when $PATH contains an executable
file or, on Windows, a parent directory of a %PATH% element contains an
file with the same name as the %PATH% element but with one of the
%PATHEXT% extension (ex: C:\utils\bin is in PATH, and C:\utils\bin.exe
exists).
Fix incorrect expansion of ".." when $PATH contains an element which is
an the concatenation of the path to an executable file (or on Windows
a path that can be expanded to an executable by appending a %PATHEXT%
extension), a path separator and a name.
"", "." and ".." are now rejected early with ErrNotFound.
Fixes CVE-2025-47906
Fixes #74466
Change-Id: Ie50cc0a660fce8fbdc952a7f2e05c36062dcb50e
Reviewed-on: https://go-review.googlesource.com/c/go/+/685755
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Auto-Submit: Damien Neil <dneil@google.com>
Reviewed-by: Roland Shoemaker <roland@golang.org>
Reviewed-by: Damien Neil <dneil@google.com>
Diffstat (limited to 'src/os/exec/dot_test.go')
| -rw-r--r-- | src/os/exec/dot_test.go | 44 |
1 files changed, 44 insertions, 0 deletions
diff --git a/src/os/exec/dot_test.go b/src/os/exec/dot_test.go index 1bf0d9c760..b95639e6c8 100644 --- a/src/os/exec/dot_test.go +++ b/src/os/exec/dot_test.go @@ -177,4 +177,48 @@ func TestLookPath(t *testing.T) { } } }) + + checker := func(test string) func(t *testing.T) { + return func(t *testing.T) { + t.Helper() + t.Logf("PATH=%s", os.Getenv("PATH")) + p, err := LookPath(test) + if err == nil { + t.Errorf("%q: error expected, got nil", test) + } + if p != "" { + t.Errorf("%q: path returned should be \"\". Got %q", test, p) + } + } + } + + // Reference behavior for the next test + t.Run(pathVar+"=$OTHER2", func(t *testing.T) { + t.Run("empty", checker("")) + t.Run("dot", checker(".")) + t.Run("dotdot1", checker("abc/..")) + t.Run("dotdot2", checker("..")) + }) + + // Test the behavior when PATH contains an executable file which is not a directory + t.Run(pathVar+"=exe", func(t *testing.T) { + // Inject an executable file (not a directory) in PATH. + // Use our own binary os.Args[0]. + t.Setenv(pathVar, testenv.Executable(t)) + t.Run("empty", checker("")) + t.Run("dot", checker(".")) + t.Run("dotdot1", checker("abc/..")) + t.Run("dotdot2", checker("..")) + }) + + // Test the behavior when PATH contains an executable file which is not a directory + t.Run(pathVar+"=exe/xx", func(t *testing.T) { + // Inject an executable file (not a directory) in PATH. + // Use our own binary os.Args[0]. + t.Setenv(pathVar, filepath.Join(testenv.Executable(t), "xx")) + t.Run("empty", checker("")) + t.Run("dot", checker(".")) + t.Run("dotdot1", checker("abc/..")) + t.Run("dotdot2", checker("..")) + }) } |
