]> Cypherpunks repositories - gostls13.git/commitdiff
syscall: reduce memory allocated by UTF16FromString
authorFrediano Ziglio <freddy77@gmail.com>
Thu, 4 May 2023 10:25:29 +0000 (11:25 +0100)
committerGopher Robot <gobot@golang.org>
Thu, 4 May 2023 17:28:54 +0000 (17:28 +0000)
The function allocated a buffer larger than needed.
Fixes #59967.

Signed-off-by: Frediano Ziglio <frediano.ziglio@nextdlp.com>
Change-Id: I5f30a135acf5f27d6c2ef4bc4abef5144da4dc94
Reviewed-on: https://go-review.googlesource.com/c/go/+/492575
Auto-Submit: Bryan Mills <bcmills@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Carlos Amedee <carlos@golang.org>
Run-TryBot: Bryan Mills <bcmills@google.com>
Reviewed-by: Quim Muntal <quimmuntal@gmail.com>
Reviewed-by: Bryan Mills <bcmills@google.com>
src/syscall/syscall_windows.go
src/syscall/syscall_windows_test.go

index c34f0199eaff5b60623ee4fb756e6d6a662ed0a0..8687d1cc21fba3113f580ff7536be7dffee52396 100644 (file)
@@ -42,9 +42,13 @@ func UTF16FromString(s string) ([]uint16, error) {
        if bytealg.IndexByteString(s, 0) != -1 {
                return nil, EINVAL
        }
-       // In the worst case all characters require two uint16.
-       // Also account for the terminating NULL character.
-       buf := make([]uint16, 0, len(s)*2+1)
+       // Valid UTF-8 characters between 1 and 3 bytes require one uint16.
+       // Valid UTF-8 characters of 4 bytes require two uint16.
+       // Bytes with invalid UTF-8 encoding require maximum one uint16 per byte.
+       // So the number of UTF-8 code units (len(s)) is always greater or
+       // equal than the number of UTF-16 code units.
+       // Also account for the terminating NUL character.
+       buf := make([]uint16, 0, len(s)+1)
        for _, r := range s {
                buf = utf16.AppendRune(buf, r)
        }
index 3b567218e2b50da3540dba82ee9ccf0e11b10d07..23041ee09a00c0e939df6f16c0fb44ed3bcd1346 100644 (file)
@@ -169,3 +169,31 @@ int main(int argc, char *argv[])
                t.Fatalf("c program output is wrong: got %q, want %q", have, want)
        }
 }
+
+func FuzzUTF16FromString(f *testing.F) {
+       f.Add("hi")           // ASCII
+       f.Add("รข")            // latin1
+       f.Add("ใญใ“")           // plane 0
+       f.Add("๐Ÿ˜ƒ")            // extra Plane 0
+       f.Add("\x90")         // invalid byte
+       f.Add("\xe3\x81")     // truncated
+       f.Add("\xe3\xc1\x81") // invalid middle byte
+
+       f.Fuzz(func(t *testing.T, tst string) {
+               res, err := syscall.UTF16FromString(tst)
+               if err != nil {
+                       if strings.Contains(tst, "\x00") {
+                               t.Skipf("input %q contains a NUL byte", tst)
+                       }
+                       t.Fatalf("UTF16FromString(%q): %v", tst, err)
+               }
+               t.Logf("UTF16FromString(%q) = %04x", tst, res)
+
+               if len(res) < 1 || res[len(res)-1] != 0 {
+                       t.Fatalf("missing NUL terminator")
+               }
+               if len(res) > len(tst)+1 {
+                       t.Fatalf("len(%04x) > len(%q)+1", res, tst)
+               }
+       })
+}