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) {
}
}
+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