back to research
LARP-2026-014memory18 min read

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 file

Exploitation

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.

Figure 1. Heap layout before and after the overflow

Timeline

  1. 02 Jul 2026Reported to the vendor with a PoC
  2. 05 Jul 2026Vendor confirmed the bug3 days, great response
  3. 30 Sep 2026Fix released
  4. 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.

kaze and m0th
back to research