A two-byte heap overflow in a font shaping engine
The engine sizes a buffer from one field in the font and copies data based on another. A crafted font makes them disagree, which gives a two-byte heap overflow. We used it to corrupt a function pointer.
Font parsers are old, heavily optimized, and they process untrusted input every time someone opens a document or a web page. This one had been fuzzed for years, so instead of fuzzing it again we sat down and read the code.
The bug
The engine allocates a buffer using a record count from the font file, then copies data into it using a separate length field from the same file. Nothing checks that the two match. When the length is larger, the copy writes two bytes past the end of the buffer.
uint16_t n = read_u16(tbl + 2); // count, from the file
rec_t *buf = alloc(n * sizeof(rec_t));
/* copy trailing records */
memcpy(buf, src, hdr->len); // length, also from the fileExploitation
Two bytes is not a lot, but the buffer sits right before an object that holds a function pointer. With some heap grooming, the overflow lands on the low two bytes of that pointer. That partial overwrite is enough to redirect execution.
Timeline
- 02 Jul 2026Reported to the vendor with a PoC
- 05 Jul 2026Vendor confirmed the bug3 days, great response
- 30 Sep 2026Fix released
- 21 Oct 2026Write-up published
The fix was one bounds check. If a file gives you two sizes for the same thing, check that they match.