CVE-2026-49919 AI-generated analysis
platform/external/freetype, sfnt driver, COLR (color glyph layer) blending in src/sfnt/ttcolr.c
Replaces an unchecked `size = rows * pitch; FT_ALLOC(buf, size)` in tt_face_colr_blend_layer (src/sfnt/ttcolr.c) with FT_ALLOC_MULT(buf, rows, pitch), so the FreeType memory layer detects the multiplication overflow instead of the code allocating an undersized buffer.
Root cause
In src/sfnt/ttcolr.c tt_face_colr_blend_layer, the temporary buffer was allocated as FT_ALLOC(buf, size), where size was the plain product rows * pitch with no overflow check. If that product wraps, FT_ALLOC receives a small size and the allocation succeeds with an undersized buffer. Later code in the function works with buf and dstSlot->bitmap.buffer (only the start of that code is shown). The commit message says the overflow is now detected in ft_mem_qrealloc and references upstream issue #1389.
How the fix works
- src/sfnt/ttcolr.c:tt_face_colr_blend_layer: removes the local computation `size = rows * pitch;` and replaces `FT_ALLOC( buf, size )` with `FT_ALLOC_MULT( buf, rows, pitch )`. FT_ALLOC_MULT passes the count and item size separately to the FreeType memory layer, which (per the commit message) detects the multiplication overflow in ft_mem_qrealloc. On failure the function returns `error` before reaching the code that follows the allocation.
- Single file, single hunk, one line added and two removed; no other code paths are touched.
Completeness
- Covers only the one allocation of `buf` in tt_face_colr_blend_layer. The overflow-prone product is no longer computed by hand there.
- The diff adds no explicit validation of rows or pitch. It relies only on the allocator's overflow check at allocation time.
- The material does not show the rest of tt_face_colr_blend_layer or the other FT_ALLOC sites in ttcolr.c. Whether other hand-computed sizes exist in the same file cannot be judged from the material.
- The declaration of the local `size` variable is not shown in the hunk. If it is still declared and now unused, the diff does not remove it.
Behavior changes
- When rows * pitch would overflow, tt_face_colr_blend_layer now returns the error from the allocator instead of continuing with a small buffer. For such fonts the color glyph layer blend is aborted.
- No behavior change for sizes that do not overflow.
Per major
- Android 14: same fix: platform/external/freetype ab9caf444825 in android-security-14.0.0_r29, identical hunk at line 1803 (cherry-pick of 4581ed553986, Change-Id I2a11ad1dcce5).
- Android 15: same fix: platform/external/freetype 9f67316aa41d in android-security-15.0.0_r17, identical hunk at line 1803.
- Android 16: same fix: platform/external/freetype 6770ef4d9faf in android-security-16.0.0_r8, identical hunk at line 1803 (same pre/post blob ids as Android 15).
- Android 17: same fix: platform/external/freetype 65f3c6ba20e7 in android-security-17.0.0_r1, identical hunk shifted to line 1805.
Unknowns
- The body of tt_face_colr_blend_layer (how rows and pitch are derived, the copy loop and its bounds) is not in the provided context. The context shown is tt_face_load_colr and tt_face_free_colr.
- Which out-of-bounds access, if any, followed the undersized allocation before the fix.
- The exact error code returned when ft_mem_qrealloc detects the overflow.
- Whether the local `size` variable is still declared or used elsewhere in the function after the change.
- Which Android font-rendering paths actually exercise COLR layer blending through FreeType (Skia/hwui vs other consumers).