From 133144001da395fba3ddc9bb20eb1a1a63b67456 Mon Sep 17 00:00:00 2001 From: Eidolon Date: Tue, 2 Jan 2024 15:26:51 -0600 Subject: [PATCH] Defer ghost deallocation til FreeGhosts Fixes KartKrew/Kart#824 The for-loop attempts to read `g` after the object it points to has already been freed by Z_Free. Instead, we add a new `done` field, and mark it when hitting the end of the demo, and skip ghosts in the ghost list which have it set. --- src/g_demo.c | 18 ++++++++++++------ src/g_demo.h | 1 + 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/src/g_demo.c b/src/g_demo.c index 5de64ce40..eb0b0302b 100644 --- a/src/g_demo.c +++ b/src/g_demo.c @@ -1226,11 +1226,16 @@ void G_ConsGhostTic(INT32 playernum) void G_GhostTicker(void) { demoghost *g,*p; - for(g = ghosts, p = NULL; g; g = g->next) + for (g = ghosts, p = NULL; g; g = g->next) { UINT16 ziptic; UINT8 xziptic; + if (g->done) + { + continue; + } + // Pause jhosts that cross until we cross ourself. if (g->linecrossed && !linecrossed) continue; @@ -1276,7 +1281,9 @@ readghosttic: } } else - I_Error("Ghost is not a record attack ghost DXD"); //@TODO lmao don't blow up like this + { + I_Error("Ghost is not a record attack ghost DXD (ziptic = %u)", ziptic); //@TODO lmao don't blow up like this + } ziptic = READUINT8(g->p); } @@ -1532,12 +1539,11 @@ skippedghosttic: if (follow) follow->fuse = TICRATE; #endif + g->done = true; if (p) + { p->next = g->next; - else - ghosts = g->next; - Z_Free(g->skinlist); - Z_Free(g); + } continue; } diff --git a/src/g_demo.h b/src/g_demo.h index 89e7f6fd7..dcfd920fc 100644 --- a/src/g_demo.h +++ b/src/g_demo.h @@ -170,6 +170,7 @@ struct demoghost { UINT16 version; UINT8 numskins; boolean linecrossed; + boolean done; democharlist_t *skinlist; mobj_t oldmo, *mo; struct demoghost *next;