Fix memory-amplification DoS via uint16 underflow in ReadGlyph#190
Open
XavLimSG wants to merge 1 commit intogoogle:masterfrom
Open
Fix memory-amplification DoS via uint16 underflow in ReadGlyph#190XavLimSG wants to merge 1 commit intogoogle:masterfrom
XavLimSG wants to merge 1 commit intogoogle:masterfrom
Conversation
Validate that endPtsOfContours values are monotonically increasing in ReadGlyph(). The TrueType spec requires this, but it was not enforced. When endPtsOfContours values decrease, the uint16 subtraction at glyph.cc:98 wraps to a large value (up to 65535), causing each affected contour to allocate ~65K Point structs. A crafted font with alternating high/low endpoint values triggers massive heap allocations from tiny input — a 2.3 KB font forces 191 MB of RSS in the real woff2_compress binary (85,063x amplification). With more contours this scales to 12+ GB. The fix rejects fonts with non-monotonic endPtsOfContours before the subtraction occurs.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Hey, found a memory-amplification DoS in
ReadGlyph()while auditing the codebase. Figured I'd just submit the fix directly since it's a one-liner.The Bug
ReadGlyph()inglyph.cccomputes per-contour point counts by subtracting consecutiveendPtsOfContoursvalues:The TrueType spec requires
endPtsOfContoursto be monotonically increasing, but this isn't validated. If the values decrease, theuint16_tsubtraction wraps —100 - 200becomes65436— and each affected contour allocates ~65KPointstructs on the heap.An attacker can alternate high/low values across many contours to force massive allocations from a tiny input.
Validated Impact
Tested against the real
woff2_compressbinary (not a test harness), measuring RSS via/proc/<pid>/statmfrom an external monitor process:A 2.3 KB crafted
.ttfforces the real binary to consume 191 MB before it crashes out. Scales linearly — with 32K contours in a ~65KB font you're looking at ~12 GB.The attack surface is the encoder path:
ConvertTTFToWOFF2→NormalizeFontCollection→NormalizeGlyphs→ReadGlyph. Anything that accepts untrusted.ttf/.ttcfiles and runs them through the woff2 encoder is affected. The decoder (ConvertWOFF2ToTTF) uses a separate transformed glyph format and is not affected by this specific issue.The Fix
One check before the subtraction — reject the font if
endPtsOfContoursvalues aren't monotonically increasing:This is consistent with the TrueType spec requirement and how other font parsers handle it.
Testing
After the fix, same malicious inputs:
Legitimate fonts unaffected — tested all 6 DejaVu system fonts:
DejaVuSans.ttf(757 KB) → compresses and round-trips fineDejaVuSans-Bold.ttf,DejaVuSerif-Bold.ttf,DejaVuSerif.ttf,DejaVuSansMono.ttf,DejaVuSansMono-Bold.ttf— all compress successfullyNo regressions on any well-formed font.