Commit 06106cb
committed
gfx/drivers_font_renderer: fix OOM NULL-deref in bitmapfont atlas buffer and coretext bitmapData
Two NULL-deref bugs reachable under OOM in the font renderer
backends.
=== bitmapfont.c (font_renderer_bmp_init) ===
font_renderer_bmp_init allocates a scaled atlas buffer and then
rasterises 256 glyphs into it:
handle->atlas.buffer = (uint8_t*)calloc(
handle->atlas.width * handle->atlas.height, 1);
for (i = 0; i < BMP_ATLAS_SIZE; i++)
{
...
char_to_texture(handle, i, x, y);
...
}
The calloc was unchecked. char_to_texture does
uint8_t *target = handle->atlas.buffer + atlas_x +
atlas_y * handle->atlas.width;
...
dst[xo + yo * handle->atlas.width] = col;
which NULL-derefs on OOM.
Fixed with a NULL-check immediately after the calloc, freeing
the already-allocated 'handle' and returning NULL. The
font_renderer_bmp_free teardown path is NULL-safe so we could
alternatively have fallen through to that, but the direct
free(handle)+return NULL is a minimal-diff fix.
=== coretext.c (ct_font_renderer_get_glyph) ===
The per-glyph rendering path calloc's a scratch bitmap, passes
it to CGBitmapContextCreate, draws the glyph via CoreText, then
byte-wise copies the bitmap into the shared atlas:
bitmapData = calloc(slot->glyph.height, slot->glyph.width);
offscreen = CGBitmapContextCreate(bitmapData, ...);
if (!offscreen) { free(bitmapData); return false; }
...
src = (const uint8_t*)bitmapData;
for (r = 0; r < slot->glyph.height; r++)
for (c = 0; c < slot->glyph.width; c++)
dst[r * handle->atlas.width + c] =
src[r * slot->glyph.width + c];
CGBitmapContextCreate is NULL-tolerant in its 'data' parameter
- when NULL it allocates its own backing store. So on OOM
the flow was:
1. bitmapData = NULL.
2. CGBitmapContextCreate creates a valid context with its
own backing store.
3. CoreText renders into that internal store.
4. The 'src' copy loop dereferences bitmapData (NULL) and
segfaults.
A subtle failure mode because the first two steps succeed
and the third (internally) works - only the atlas copy
crashes, which in a stack trace looks like a CoreText /
GPU issue rather than an OOM.
Fixed with a NULL-check on bitmapData before the
CGBitmapContextCreate call. Returning false here matches the
return-false behaviour on the !offscreen branch below - the
caller handles missing glyphs gracefully (glyph slot stays
uninitialised, rendering falls back to whitespace).
=== Swept-clean in the same pass ===
Verified via visual inspection of every calloc/malloc/realloc
call in the renderer files that all other sites were already
NULL-checked:
- bitmapfont.c : 3 sites (lines 58, 67, 75) all guarded.
- bitmapfont_6x10.c / bitmapfont_10x10.c: all sites guarded.
- stb.c / stb_unicode.c: all sites guarded.
- freetype.c : all sites guarded.
- font_driver.c: single site guarded (prior fix, commit
landed earlier).
Thread-safety: both bugs are in one-shot init paths called
from the main video thread at atlas creation time; no
concurrency concerns.
Reachability: OOM on a 512x512 calloc (bitmapfont atlas) or a
much smaller per-glyph calloc (coretext bitmapData) is
unlikely on desktop builds but realistic on memory-constrained
embedded targets where RetroArch runs - especially the
bitmapfont path which is the fallback when no TTF renderer is
available.1 parent 5b73ff7 commit 06106cb
2 files changed
Lines changed: 19 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
185 | 185 | | |
186 | 186 | | |
187 | 187 | | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
| 194 | + | |
| 195 | + | |
| 196 | + | |
| 197 | + | |
| 198 | + | |
188 | 199 | | |
189 | 200 | | |
190 | 201 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
291 | 291 | | |
292 | 292 | | |
293 | 293 | | |
| 294 | + | |
| 295 | + | |
| 296 | + | |
| 297 | + | |
| 298 | + | |
| 299 | + | |
| 300 | + | |
| 301 | + | |
294 | 302 | | |
295 | 303 | | |
296 | 304 | | |
| |||
0 commit comments