diff options
author | Qi Xiao <xiaq@google.com> | 2023-06-11 23:29:26 +0100 |
---|---|---|
committer | Gopher Robot <gobot@golang.org> | 2023-06-14 13:30:22 +0000 |
commit | ba4c6d1d6e36b9a4beee3f501fa8ad2e044d0768 (patch) | |
tree | 15ece5d11a751f9bf2f0b4bf264336f48abcfaf4 | |
parent | c3db64c0f45e8f2d75c5b59401e0fc925701b6f4 (diff) | |
download | go-ba4c6d1d6e36b9a4beee3f501fa8ad2e044d0768.tar.gz go-ba4c6d1d6e36b9a4beee3f501fa8ad2e044d0768.zip |
syscall: Fix Getwd on Windows to correctly handle long paths.
Fixes #60051.
Change-Id: Ia68ca0493912cb09d8c1d36a144bf0725842af1d
Reviewed-on: https://go-review.googlesource.com/c/go/+/502415
Auto-Submit: Bryan Mills <bcmills@google.com>
Run-TryBot: Quim Muntal <quimmuntal@gmail.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Bryan Mills <bcmills@google.com>
-rw-r--r-- | src/syscall/syscall_windows.go | 18 | ||||
-rw-r--r-- | src/syscall/syscall_windows_test.go | 24 |
2 files changed, 38 insertions, 4 deletions
diff --git a/src/syscall/syscall_windows.go b/src/syscall/syscall_windows.go index 9f1b384de4..e348905abf 100644 --- a/src/syscall/syscall_windows.go +++ b/src/syscall/syscall_windows.go @@ -533,11 +533,21 @@ const ImplementsGetwd = true func Getwd() (wd string, err error) { b := make([]uint16, 300) - n, e := GetCurrentDirectory(uint32(len(b)), &b[0]) - if e != nil { - return "", e + // The path of the current directory may not fit in the initial 300-word + // buffer when long path support is enabled. The current directory may also + // change between subsequent calls of GetCurrentDirectory. As a result, we + // need to retry the call in a loop until the current directory fits, each + // time with a bigger buffer. + for { + n, e := GetCurrentDirectory(uint32(len(b)), &b[0]) + if e != nil { + return "", e + } + if int(n) <= len(b) { + return UTF16ToString(b[:n]), nil + } + b = make([]uint16, n) } - return UTF16ToString(b[0:n]), nil } func Chdir(path string) (err error) { diff --git a/src/syscall/syscall_windows_test.go b/src/syscall/syscall_windows_test.go index 7b31a863c3..81285e9a38 100644 --- a/src/syscall/syscall_windows_test.go +++ b/src/syscall/syscall_windows_test.go @@ -180,6 +180,30 @@ int main(int argc, char *argv[]) } } +func TestGetwd_DoesNotPanicWhenPathIsLong(t *testing.T) { + // Regression test for https://github.com/golang/go/issues/60051. + + // The length of a filename is also limited, so we can't reproduce the + // crash by creating a single directory with a very long name; we need two + // layers. + a200 := strings.Repeat("a", 200) + dirname := filepath.Join(t.TempDir(), a200, a200) + + err := os.MkdirAll(dirname, 0o700) + if err != nil { + t.Skipf("MkdirAll failed: %v", err) + } + err = os.Chdir(dirname) + if err != nil { + t.Skipf("Chdir failed: %v", err) + } + // Change out of the temporary directory so that we don't inhibit its + // removal during test cleanup. + defer os.Chdir(`\`) + + syscall.Getwd() +} + func FuzzUTF16FromString(f *testing.F) { f.Add("hi") // ASCII f.Add("รข") // latin1 |