aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorQi Xiao <xiaq@google.com>2023-06-11 23:29:26 +0100
committerGopher Robot <gobot@golang.org>2023-06-14 13:30:22 +0000
commitba4c6d1d6e36b9a4beee3f501fa8ad2e044d0768 (patch)
tree15ece5d11a751f9bf2f0b4bf264336f48abcfaf4
parentc3db64c0f45e8f2d75c5b59401e0fc925701b6f4 (diff)
downloadgo-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.go18
-rw-r--r--src/syscall/syscall_windows_test.go24
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