Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-ID: <CALrEReYUaSySTPo_N1qYv3ah_4MGf-sCTZbEEm6dkuVcHGtNVA@mail.gmail.com>
Date: Thu, 19 Mar 2026 21:45:20 +0500
From: Ali Raza <elirazamumtaz@...il.com>
To: oss-security@...ts.openwall.com
Subject: Off-by-one heap buffer overflow in libuv

Last few days ago I found an off-by-one heap buffer overflow in libuv.
Off-by-one NUL write past a heap buffer in `uv_utf16_to_wtf8()` when called
from the Windows TTY line-read path. When a user types or pastes CJK
characters into a Windows console application backed by libuv, a 1-byte
out-of-bounds NUL write occurs if the read buffer size is divisible by 3.

I found this while reading through the TTY code. `uv_utf16_to_wtf8()` in
src/idna.c unconditionally writes a NUL terminator at:
```c
*target++ = '\0';   // idna.c:550 -- writes at target[target_len] when
buffer is full
```

The function's own comment says `*target_len_ptr` should be the length
_excluding_ space for NUL. Two callers in util.c handle this correctly:
```c
utf8_len = *size_ptr - 1; /* Reserve space for NUL */    // util.c:126
*size -= 1; /* Reserve space for NUL. */                   // util.c:1121
```

But the TTY line-read path passes the full buffer size without the
subtraction:
```c
read_bytes = bytes;    // tty.c:558 — should be bytes - 1
uv_utf16_to_wtf8(utf16, read_chars,
                 &handle->tty.rd.read_line_buffer.base,
                 &read_bytes);
```

The overflow happens when all the input characters encode to exactly 3
UTF-8 bytes each (BMP characters in U+0800–U+FFFF range, like CJK
ideographs). The TTY code computes `chars = bytes / 3` (tty.c:540), so when
`bytes % 3 == 0`, the worst-case output `chars * 3` equals `bytes` exactly,
and the NUL terminator writes one byte past the buffer.

The buffer size comes from the application's `alloc_cb`. libuv suggests
8192 (not divisible by 3), but any application returning a size that's
divisible by 3 hits this.

Introduced in v1.47.0 (commit f3889085, PR #4021), still present on v1.x
HEAD.


Best

Ali Raza (@locus-x64)

Powered by blists - more mailing lists

Please check out the Open Source Software Security Wiki, which is counterpart to this mailing list.

Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.