Report the failures that used to be crashes
Closes Defects items 30 and 31 and Known-and-still-open items 1, 2, 5, 9 and 11. Both string accessors in json_helpers.c ended their ATTEMPT block with FINISH(errctx, false), which swallows the failure, and then strncpy'd through the pointer akgl_heap_next_string never set. So the one condition the pool exists to report -- it is full, which in practice means something is not releasing -- arrived as a segfault somewhere else entirely. It is FINISH(errctx, true) now, and tests/json_helpers.c claims every slot and asserts AKGL_ERR_HEAP comes back out of both. That test segfaults against the old code, which is also how the tilemap leak test in the previous commit confirmed this one. akgl_tilemap_release tested layers[i].texture and destroyed tilesets[i].texture, so every tileset texture was freed twice on one release and no image layer's texture was freed at all. Pointers are cleared as they go, so a second release is safe instead of a use-after-free. akgl_game_update_fps called game.lowfpsfunc() unguarded, on a path taken on frame one because fps is 0 for the first second. Only akgl_game_init installs it, and renderer.h documents the other path deliberately -- a host that owns its window binds a backend instead. It installs the default when it finds NULL. akgl_controller_pushmap and akgl_controller_default checked only the upper bound, so a negative id indexed before akgl_controlmaps. The two test-harness helpers were quietly worthless. akgl_render_and_compare drew t1 on both passes, so it always reported a match and every image assertion built on it asserted nothing; and akgl_compare_sdl_surfaces memcmp'd s1->pitch * s1->h bytes out of both surfaces without checking that the second was the same size, so a smaller one was read past its end. Both fixed, both tested. tests/util.c also now calls the collide-point test it has defined and never run. 25/25 pass, memcheck clean, reindent --check and check_error_protocol clean. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
26
src/util.c
26
src/util.c
@@ -224,6 +224,30 @@ akerr_ErrorContext *akgl_compare_sdl_surfaces(SDL_Surface *s1, SDL_Surface *s2)
|
||||
PREPARE_ERROR(errctx);
|
||||
FAIL_ZERO_RETURN(errctx, s1, AKERR_NULLPOINTER, "NULL Surface pointer");
|
||||
FAIL_ZERO_RETURN(errctx, s2, AKERR_NULLPOINTER, "NULL Surface pointer");
|
||||
// Geometry first. The memcmp reads s1->pitch * s1->h bytes out of *both*,
|
||||
// so a smaller s2 was read past its end rather than reported as a
|
||||
// mismatch -- and a differing pitch or format made the comparison
|
||||
// meaningless even when it did not run off.
|
||||
FAIL_NONZERO_RETURN(
|
||||
errctx,
|
||||
((s1->w != s2->w) || (s1->h != s2->h)),
|
||||
AKERR_VALUE,
|
||||
"Comparison surfaces differ in size: %dx%d against %dx%d",
|
||||
s1->w, s1->h, s2->w, s2->h);
|
||||
FAIL_NONZERO_RETURN(
|
||||
errctx,
|
||||
(s1->pitch != s2->pitch),
|
||||
AKERR_VALUE,
|
||||
"Comparison surfaces differ in pitch: %d against %d",
|
||||
s1->pitch, s2->pitch);
|
||||
FAIL_NONZERO_RETURN(
|
||||
errctx,
|
||||
(s1->format != s2->format),
|
||||
AKERR_VALUE,
|
||||
"Comparison surfaces differ in pixel format: %s against %s",
|
||||
SDL_GetPixelFormatName(s1->format), SDL_GetPixelFormatName(s2->format));
|
||||
FAIL_ZERO_RETURN(errctx, s1->pixels, AKERR_NULLPOINTER, "First surface has no pixels");
|
||||
FAIL_ZERO_RETURN(errctx, s2->pixels, AKERR_NULLPOINTER, "Second surface has no pixels");
|
||||
FAIL_NONZERO_RETURN(errctx, memcmp(s1->pixels, s2->pixels, (s1->pitch * s1->h)), AKERR_VALUE, "Comparison surfaces are not equal");
|
||||
SUCCEED_RETURN(errctx);
|
||||
}
|
||||
@@ -261,7 +285,7 @@ akerr_ErrorContext *akgl_render_and_compare(SDL_Texture *t1, SDL_Texture *t2, in
|
||||
|
||||
SDL_RenderClear(akgl_renderer->sdl_renderer);
|
||||
|
||||
CATCH(errctx, akgl_renderer->draw_texture(akgl_renderer, t1, &src, &dest, 0, NULL, SDL_FLIP_NONE));
|
||||
CATCH(errctx, akgl_renderer->draw_texture(akgl_renderer, t2, &src, &dest, 0, NULL, SDL_FLIP_NONE));
|
||||
s2 = SDL_RenderReadPixels(akgl_renderer->sdl_renderer, &read);
|
||||
FAIL_ZERO_BREAK(errctx, s2, AKGL_ERR_SDL, "Failed to read pixels from renderer");
|
||||
|
||||
|
||||
Reference in New Issue
Block a user