CallFunc_SetThingProperty: Get next mobj in TID chain at start of loop

In cases where state/property set can cause instant deletion, definitely interrupts FindMobjFromTID iteration after one step and potentially uses after free

Also adds comment warnings to this effect near ways to find P_FindMobjFromTID, and updates P_ProcessSpecial even though we could probably stand to rip it out now
This commit is contained in:
toaster 2025-05-26 15:22:30 +01:00
parent 1cdf381aba
commit 5e7cce9047
4 changed files with 15 additions and 5 deletions

View file

@ -3589,13 +3589,15 @@ bool CallFunc_SetThingProperty(ACSVM::Thread *thread, const ACSVM::Word *argV, A
INT32 value = 0; INT32 value = 0;
tag = argV[0]; tag = argV[0];
mobj = P_FindMobjFromTID(tag, mobj, info->mo); mobj_t *next = P_FindMobjFromTID(tag, mobj, info->mo);
property = argV[1]; property = argV[1];
value = argV[2]; value = argV[2];
while (mobj != NULL) while ((mobj = next) != NULL)
{ {
// First in case of deletion. (Can't check for value == S_NULL because of A_ calls, etc)
next = P_FindMobjFromTID(tag, mobj, info->mo);
#define PROP_READONLY(x, y) \ #define PROP_READONLY(x, y) \
case x: \ case x: \
@ -3830,8 +3832,6 @@ bool CallFunc_SetThingProperty(ACSVM::Thread *thread, const ACSVM::Word *argV, A
} }
} }
mobj = P_FindMobjFromTID(tag, mobj, info->mo);
#undef PROP_FLAGS #undef PROP_FLAGS
#undef PROP_SCALE #undef PROP_SCALE
#undef PROP_MOBJ #undef PROP_MOBJ

View file

@ -612,6 +612,9 @@ void P_InitTIDHash(void);
void P_AddThingTID(mobj_t *mo); void P_AddThingTID(mobj_t *mo);
void P_RemoveThingTID(mobj_t *mo); void P_RemoveThingTID(mobj_t *mo);
void P_SetThingTID(mobj_t *mo, mtag_t tid); void P_SetThingTID(mobj_t *mo, mtag_t tid);
// This function cannot be safely called after *i is removed!
// Please call at start of loops if *i is to be mutated
mobj_t *P_FindMobjFromTID(mtag_t tid, mobj_t *i, mobj_t *activator); mobj_t *P_FindMobjFromTID(mtag_t tid, mobj_t *i, mobj_t *activator);
void P_DeleteMobjStringArgs(mobj_t *mobj); void P_DeleteMobjStringArgs(mobj_t *mobj);

View file

@ -15417,6 +15417,8 @@ void P_SetThingTID(mobj_t *mo, mtag_t tid)
// //
// P_FindMobjFromTID // P_FindMobjFromTID
// Mobj tag search function. // Mobj tag search function.
// This function cannot be safely called after *i is removed!
// Please call at start of loops if *i is to be mutated
// //
mobj_t *P_FindMobjFromTID(mtag_t tid, mobj_t *i, mobj_t *activator) mobj_t *P_FindMobjFromTID(mtag_t tid, mobj_t *i, mobj_t *activator)
{ {

View file

@ -3275,8 +3275,13 @@ boolean P_ProcessSpecial(activator_t *activator, INT16 special, INT32 *args, cha
return false; return false;
} }
while ((targetThing = P_FindMobjFromTID(args[1], targetThing, mo)) != NULL) mobj_t *next = P_FindMobjFromTID(args[1], targetThing, mo);
while ((targetThing = next) != NULL)
{ {
// First in case of deletion. (Can't check for state == S_NULL because of A_ calls, etc)
next = P_FindMobjFromTID(args[1], targetThing, mo);
if (targetThing->player != NULL) if (targetThing->player != NULL)
{ {
continue; continue;