Check the renderer backend before drawing text

akgl_text_rendertextat() called renderer->draw_texture() with no check on
the global renderer, its sdl_renderer or the function pointer itself, so a
backend that has an SDL_Renderer but was never bound segfaults on the first
line of text -- the state akgl_render_bind2d() exists to get a host out of.
All three are now checked, with AKERR_NULLPOINTER as the draw entry points
report, and checked before anything is rasterized rather than after.

tests/text.c grows a software renderer with a bound backend and covers all
three refusals plus the successful draw, wrapped and unwrapped: src/text.c
goes from 58% to 100% line coverage. A made-up SDL_Renderer pointer is not
enough to test this -- SDL refuses the bogus handle on its own and the call
fails for the wrong reason, which a deleted check survives.

Also documents what the tests found: SDL_ttf refuses the empty string, so
drawing an empty line is an error while measuring one is not. Filed in
TODO.md rather than pinned in the suite.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-31 12:52:20 -04:00
parent ede3452c49
commit 42b53dcb20
3 changed files with 123 additions and 5 deletions

View File

@@ -39,6 +39,13 @@ akerr_ErrorContext AKERR_NOIGNORE *akgl_text_rendertextat(TTF_Font *font, char *
PREPARE_ERROR(errctx);
FAIL_ZERO_RETURN(errctx, font, AKERR_NULLPOINTER, "NULL font");
FAIL_ZERO_RETURN(errctx, text, AKERR_NULLPOINTER, "NULL text string");
// Checked before anything is rasterized, and checked at all because a
// backend that has an SDL_Renderer but was never run through
// akgl_render_bind2d has a NULL draw_texture -- which is exactly the state
// akgl_render_init2d used to be the only escape from.
FAIL_ZERO_RETURN(errctx, renderer, AKERR_NULLPOINTER, "No renderer backend");
FAIL_ZERO_RETURN(errctx, renderer->sdl_renderer, AKERR_NULLPOINTER, "No valid SDL rendering backend");
FAIL_ZERO_RETURN(errctx, renderer->draw_texture, AKERR_NULLPOINTER, "Renderer backend has no draw_texture");
if ( wraplength > 0 ) {
textsurf = TTF_RenderText_Blended_Wrapped(
font,