diff --git a/windows/syscall_windows.go b/windows/syscall_windows.go index 9cab50a9..453a7b97 100644 --- a/windows/syscall_windows.go +++ b/windows/syscall_windows.go @@ -1697,10 +1697,13 @@ func NewNTUnicodeString(s string) (*NTUnicodeString, error) { if err != nil { return nil, err } - n := uint16(len(s16) * 2) + n := len(s16) * 2 + if n > (1<<16)-1 { + return nil, syscall.EINVAL + } return &NTUnicodeString{ - Length: n - 2, // subtract 2 bytes for the NULL terminator - MaximumLength: n, + Length: uint16(n) - 2, // subtract 2 bytes for the NULL terminator + MaximumLength: uint16(n), Buffer: &s16[0], }, nil } diff --git a/windows/syscall_windows_test.go b/windows/syscall_windows_test.go index 76115384..f552b94d 100644 --- a/windows/syscall_windows_test.go +++ b/windows/syscall_windows_test.go @@ -10,6 +10,7 @@ import ( "debug/pe" "errors" "fmt" + "math" "os" "os/exec" "path/filepath" @@ -1475,21 +1476,37 @@ func TestToUnicodeEx(t *testing.T) { } func TestRoundtripNTUnicodeString(t *testing.T) { - for _, s := range []string{ - "", - "hello", - "Ƀ", - strings.Repeat("*", 32000), // NTUnicodeString works up to 2^16 byte lengths == 32768 uint16s. - // TODO: various encoding errors? - } { - ntus, err := windows.NewNTUnicodeString(s) + // NTUnicodeString maximum string length must fit in a uint16, less for terminal NUL. + maxString := strings.Repeat("*", (math.MaxUint16/2)-1) + for _, test := range []struct { + s string + wantErr bool + }{{ + s: "", + }, { + s: "hello", + }, { + s: "Ƀ", + }, { + s: maxString, + }, { + s: maxString + "*", + wantErr: true, + }, { + s: "a\x00a", + wantErr: true, + }} { + ntus, err := windows.NewNTUnicodeString(test.s) + if (err != nil) != test.wantErr { + t.Errorf("NewNTUnicodeString(%q): %v, wantErr:%v", test.s, err, test.wantErr) + continue + } if err != nil { - t.Errorf("encoding %q failed: %v", s, err) continue } s2 := ntus.String() - if s != s2 { - t.Errorf("round trip of %q = %q, wanted original", s, s2) + if test.s != s2 { + t.Errorf("round trip of %q = %q, wanted original", test.s, s2) } } }