Skip to content

Commit fb1facd

Browse files
neildgopherbot
authored andcommitted
windows: avoid uint16 overflow in NewNTUnicodeString
Fixes CVE-2026-39824 Fixes #78916 Change-Id: I344518a17d59fd81c4bb39da0b3e13be6a6a6964 Reviewed-on: https://go-review.googlesource.com/c/sys/+/770080 Reviewed-by: Neal Patel <nealpatel@google.com> Reviewed-by: Quim Muntal <quimmuntal@gmail.com> LUCI-TryBot-Result: golang-scoped@luci-project-accounts.iam.gserviceaccount.com <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Auto-Submit: Damien Neil <dneil@google.com>
1 parent 94ad893 commit fb1facd

2 files changed

Lines changed: 34 additions & 14 deletions

File tree

windows/syscall_windows.go

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1697,10 +1697,13 @@ func NewNTUnicodeString(s string) (*NTUnicodeString, error) {
16971697
if err != nil {
16981698
return nil, err
16991699
}
1700-
n := uint16(len(s16) * 2)
1700+
n := len(s16) * 2
1701+
if n > (1<<16)-1 {
1702+
return nil, syscall.EINVAL
1703+
}
17011704
return &NTUnicodeString{
1702-
Length: n - 2, // subtract 2 bytes for the NULL terminator
1703-
MaximumLength: n,
1705+
Length: uint16(n) - 2, // subtract 2 bytes for the NULL terminator
1706+
MaximumLength: uint16(n),
17041707
Buffer: &s16[0],
17051708
}, nil
17061709
}

windows/syscall_windows_test.go

Lines changed: 28 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"debug/pe"
1111
"errors"
1212
"fmt"
13+
"math"
1314
"os"
1415
"os/exec"
1516
"path/filepath"
@@ -1475,21 +1476,37 @@ func TestToUnicodeEx(t *testing.T) {
14751476
}
14761477

14771478
func TestRoundtripNTUnicodeString(t *testing.T) {
1478-
for _, s := range []string{
1479-
"",
1480-
"hello",
1481-
"Ƀ",
1482-
strings.Repeat("*", 32000), // NTUnicodeString works up to 2^16 byte lengths == 32768 uint16s.
1483-
// TODO: various encoding errors?
1484-
} {
1485-
ntus, err := windows.NewNTUnicodeString(s)
1479+
// NTUnicodeString maximum string length must fit in a uint16, less for terminal NUL.
1480+
maxString := strings.Repeat("*", (math.MaxUint16/2)-1)
1481+
for _, test := range []struct {
1482+
s string
1483+
wantErr bool
1484+
}{{
1485+
s: "",
1486+
}, {
1487+
s: "hello",
1488+
}, {
1489+
s: "Ƀ",
1490+
}, {
1491+
s: maxString,
1492+
}, {
1493+
s: maxString + "*",
1494+
wantErr: true,
1495+
}, {
1496+
s: "a\x00a",
1497+
wantErr: true,
1498+
}} {
1499+
ntus, err := windows.NewNTUnicodeString(test.s)
1500+
if (err != nil) != test.wantErr {
1501+
t.Errorf("NewNTUnicodeString(%q): %v, wantErr:%v", test.s, err, test.wantErr)
1502+
continue
1503+
}
14861504
if err != nil {
1487-
t.Errorf("encoding %q failed: %v", s, err)
14881505
continue
14891506
}
14901507
s2 := ntus.String()
1491-
if s != s2 {
1492-
t.Errorf("round trip of %q = %q, wanted original", s, s2)
1508+
if test.s != s2 {
1509+
t.Errorf("round trip of %q = %q, wanted original", test.s, s2)
14931510
}
14941511
}
14951512
}

0 commit comments

Comments
 (0)