From bd4150b90ee358c2bacbe53fe46781d3b7ed9d86 Mon Sep 17 00:00:00 2001 From: Ashnal Date: Mon, 3 Oct 2022 02:07:36 -0400 Subject: [PATCH] Fixes an issue where mobjs with shadows would never get freed, due to their reference count getting reset after having their shadows spawned, resulting in a reference count of -1 and the mobj never being freed, or a use-after-free during the shadow's thinker. Also adds some P_SetTargets to P_BlockThingsIterator to fix an inconsistency I noticed while investigating this. --- src/p_maputl.c | 4 ++++ src/p_mobj.c | 6 +++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/p_maputl.c b/src/p_maputl.c index 760e45c4..17df33a9 100644 --- a/src/p_maputl.c +++ b/src/p_maputl.c @@ -1034,7 +1034,10 @@ boolean P_BlockThingsIterator(INT32 x, INT32 y, boolean (*func)(mobj_t *)) { P_SetTarget(&bnext, mobj->bnext); // We want to note our reference to bnext here incase it is MF_NOTHINK and gets removed! if (!func(mobj)) + { + P_SetTarget(&bnext, NULL); return false; + } if (P_MobjWasRemoved(tmthing) // func just popped our tmthing, cannot continue. || (bnext && P_MobjWasRemoved(bnext))) // func just broke blockmap chain, cannot continue. { @@ -1042,6 +1045,7 @@ boolean P_BlockThingsIterator(INT32 x, INT32 y, boolean (*func)(mobj_t *)) return true; } } + P_SetTarget(&bnext, NULL); return true; } diff --git a/src/p_mobj.c b/src/p_mobj.c index 530dd37d..bfdb5a7f 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -9893,6 +9893,9 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) break; } + if (!(mobj->flags & MF_NOTHINK)) + P_AddThinker(&mobj->thinker); // Needs to come before the shadow spawn, or else the shadow's reference gets forgotten + switch (mobj->type) { case MT_PLAYER: @@ -9916,9 +9919,6 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) break; } - if (!(mobj->flags & MF_NOTHINK)) - P_AddThinker(&mobj->thinker); - // Call action functions when the state is set if (st->action.acp1 && (mobj->flags & MF_RUNSPAWNFUNC)) {