CVE-2026-58822 AI-generated analysis
platform/external/freetype, smooth rasterizer (src/smooth/ftsmooth.c)
Adds early size guards to FreeType's LCD and LCD-vertical smooth rasterizer entry points (ft_smooth_raster_lcd, ft_smooth_raster_lcdv) so bitmaps whose width/3 or rows/3 exceed 0x7FFF are rejected with Raster_Overflow instead of producing truncated 16-bit span coordinates that drive an out-of-bounds write.
Root cause
In src/smooth/ftsmooth.c, ft_smooth_raster_lcd renders the outline in direct mode with ft_smooth_lcd_spans as the span callback. That callback computes the destination as dst_line + spans->x * 3 and writes spans->len bytes at stride 3. Per the commit message and added comment, FT_Span.x is 16-bit and gets truncated when computing span x-coordinates. When that happens, the destination pointer can land before the bitmap buffer and the coverage write underflows the heap allocation. Neither ft_smooth_raster_lcd nor ft_smooth_raster_lcdv validated the bitmap dimensions before rasterizing, unlike the existing guard in ft_smooth_raster_overlap referenced by the commit message.
How the fix works
- src/smooth/ftsmooth.c:ft_smooth_raster_lcd: before setting up FT_Raster_Params, return FT_THROW( Raster_Overflow ) if bitmap->width / 3 > 0x7FFF, rejecting outlines too wide for the 16-bit FT_Span.x (per the added comment).
- src/smooth/ftsmooth.c:ft_smooth_raster_lcdv: before setting params.target/source/flags, return FT_THROW( Raster_Overflow ) if bitmap->rows / 3 > 0x7FFF, rejecting outlines that are too high for the vertical LCD path.
- No change is made to ft_smooth_lcd_spans itself or to the FT_Span type; the fix is purely a precondition check at the two entry points, single commit, 8 added lines.
Completeness
- Covers both LCD entry points: horizontal (ft_smooth_raster_lcd, width check) and vertical (ft_smooth_raster_lcdv, rows check).
- The guard is a coarse bound on bitmap dimensions, not on the actual span coordinates produced by the rasterizer; ft_smooth_lcd_spans still performs unchecked pointer arithmetic (dst_line + spans->x * 3) and relies on the caller's clip box and this new size check for safety.
- ft_smooth_raster_lcd only checks width; ft_smooth_raster_lcdv only checks rows. The material does not show whether the other dimension needs a guard in each function.
- The clip box in ft_smooth_raster_lcd is set to bitmap->width (full LCD width) while the guard bounds width/3; the material does not show how the rasterizer relates clip_box.xMax to the span x values delivered to ft_smooth_lcd_spans, so whether the guard fully prevents 16-bit truncation cannot be judged from the diff.
- ft_smooth_raster_overlap already had a similar guard per the commit message; no other function is touched by the diff.
Behavior changes
- Rendering a glyph in LCD mode with bitmap->width / 3 > 32767 now fails with FT_Err_Raster_Overflow instead of rasterizing.
- Rendering a glyph in LCD_V mode with bitmap->rows / 3 > 32767 now fails with FT_Err_Raster_Overflow instead of rasterizing.
- No change for normal-size glyphs.
Per major
- Android 14: same fix: commit 51c2994abfc5 in android-security-14.0.0_r29, identical 8-line change to src/smooth/ftsmooth.c (hunks at lines 137 and 204), 8/8 lines present.
- Android 15: same fix: commit fc6e207660f9 in android-security-15.0.0_r17, identical content, hunks offset to lines 141 and 208, 8/8 lines present.
- Android 16: same fix: commit 6ca3925a3c97 in android-security-16.0.0_r8, identical content and offsets as 15, 8/8 lines present.
- Android 17: same fix: commit 4321c90fc79e in android-security-17.0.0_r1, identical content, same hunk offsets, 8/8 lines present.
Unknowns
- How the gray rasterizer derives span x values relative to clip_box.xMax = bitmap->width in LCD direct mode (not in the material), so the precise boundary at which truncation begins, and whether width/3 <= 0x7FFF fully prevents it, is not shown.
- Whether Android system font rendering paths (Skia via hwui) actually request LCD/LCD_V render modes.
- How a sufficiently large outline reaches the renderer on Android (input source) is not shown.
- Upstream FreeType commit or version corresponding to this change is not given.