[SECURITY] Off-curve point at contour end causes OOB read in stbtt__GetGlyphShapeTT
Summary
Analysis performed with the assistance of AI-based code review tools.
A single off-curve point as the last vertex of a contour causes an out-of-bounds read in stbtt__GetGlyphShapeTT at stb_truetype.h:1780. When the last contour's only point is off-curve, the code reads vertices[off+i+1], which accesses one element past the allocated vertex array.
Environment
- File:
stb_truetype.h - Commit: 31c1ad3
- OS: Linux x86_64
- Compiler: gcc 15.2.0
- Test flags:
-fsanitize=address -g -O1
Root cause
In stbtt__GetGlyphShapeTT, when a new contour starts with an off-curve point (line 1775: start_off = !(flags & 1)), the code checks the next vertex at line 1780:
if (!(vertices[off+i+1].type & 1)) {
When this off-curve point is the final point in the glyph (i == n-1), off+i+1 evaluates to off+n, indexing one element past the allocated vertex array in this trigger.
The vertex array is allocated at line 1704. This contour's vertices are at indices off through off+n-1; accessing vertices[off+n].type performs a 1-byte read beyond the valid contour data.
Trigger
A crafted TrueType font whose glyph is a single contour containing a single off-curve point. The PoC reads the font from an external file; the TTF is generated by an included Python script (312 bytes, see gen_ttf.py). No real font is required.
Impact
A 1-byte out-of-bounds heap read from an address 12 bytes past the end of the allocated vertex buffer during glyph shape parsing. The crafted font reaches this path through stbtt_GetGlyphShape.
ASAN evidence
=================================================================
==242143==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x78cea81e0046
READ of size 1 at 0x78cea81e0046
#0 stbtt__GetGlyphShapeTT ../stb_truetype.h:1780
#1 stbtt_GetGlyphShape ../stb_truetype.h:2303
#2 main poc_truetype.c:24
0x78cea81e0046 is located 12 bytes after 42-byte region [0x78cea81e0010,0x78cea81e003a)
allocated by malloc at stb_truetype.h:1704
Full log: see attached verification data.
PoC
Attached: poc_truetype.c, gen_ttf.py
Generate the test font and run:
python3 gen_ttf.py
gcc -fsanitize=address -g -O1 poc_truetype.c -o poc_truetype -lm
./poc_truetype font.ttf
Source: nothings/stb