]> Cypherpunks.ru repositories - gostls13.git/commitdiff
syscall: Fix Getwd on Windows to correctly handle long paths.
authorQi Xiao <xiaq@google.com>
Sun, 11 Jun 2023 22:29:26 +0000 (23:29 +0100)
committerGopher Robot <gobot@golang.org>
Wed, 14 Jun 2023 13:30:22 +0000 (13:30 +0000)
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>
src/syscall/syscall_windows.go
src/syscall/syscall_windows_test.go

index 9f1b384de4362a1bf33197a77694244c4f021ea7..e348905abfe3c19cae83faf57caa156145d1d3e1 100644 (file)
@@ -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) {
index 7b31a863c3d4906995230ce7616cfd4c02be95c3..81285e9a3811d7a390eafaa6cc6061d4696dccbb 100644 (file)
@@ -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