From a4ff7e5bd4d04e85706035b2a253e7bebc20b8d2 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 13 Dec 2021 13:57:54 +0100 Subject: [PATCH] - SW: added some null checks to the SO interpolation code. It looks like this was able to access deleted sprites - by only checking for the index this never registered as a problem, but with pointers it does. --- source/games/sw/src/interpso.cpp | 45 +++++++++++++++++++++++--------- source/games/sw/src/sprite.cpp | 8 +++--- 2 files changed, 35 insertions(+), 18 deletions(-) diff --git a/source/games/sw/src/interpso.cpp b/source/games/sw/src/interpso.cpp index 37966afc9..b145ffaf2 100644 --- a/source/games/sw/src/interpso.cpp +++ b/source/games/sw/src/interpso.cpp @@ -278,18 +278,24 @@ void so_updateinterpolations(void) // Stick at beginning of domovethings bool skip = !SyncInput() && (sop->track == SO_TURRET); if (SO_EMPTY(sop) || skip) continue; + + if (interp->tic < interp->lasttic) interp->tic += synctics; for (i = 0, data = interp->data; i < interp->numinterpolations; i++, data++) { if (data->curelement == soi_sprang) { - USERp u = data->actorofang->u(); - if (u) - u->oangdiff = 0; - if (!interpolating) - data->lastangdiff = 0; - data->oldipos = data->actorofang->s().ang; + auto actorofang = data->actorofang; + if (actorofang) + { + USERp u = actorofang->u(); + if (u) + u->oangdiff = 0; + if (!interpolating) + data->lastangdiff = 0; + data->oldipos = actorofang->s().ang; + } } else data->oldipos = getvalue(*data, false); @@ -318,11 +324,17 @@ void so_dointerpolations(int32_t smoothratio) // Stick at b if (SO_EMPTY(sop) || skip) continue; - for (i = 0; i < interp->numinterpolations; i++) - interp->data[i].bakipos = (interp->data[i].curelement == soi_sprang) ? - interp->data[i].actorofang->s().ang : - getvalue(interp->data[i], false); + for (i = 0; i < interp->numinterpolations; i++) + { + auto actorofang = interp->data[i].actorofang; + if (interp->data[i].curelement >= soi_sprx && actorofang == nullptr) + continue; // target went poof. + + interp->data[i].bakipos = (interp->data[i].curelement == soi_sprang) ? + actorofang->s().ang : + getvalue(interp->data[i], false); + } if (interp->tic == 0) // Only if the SO has just moved { for (i = 0, data = interp->data; i < interp->numinterpolations; i++, data++) @@ -331,8 +343,12 @@ void so_dointerpolations(int32_t smoothratio) // Stick at b data->lastoldipos = data->oldipos; if (data->curelement == soi_sprang) { - USERp u = data->actorofang->u(); - data->lastangdiff = u ? u->oangdiff : 0; + auto actorofang = data->actorofang; + if (actorofang) + { + USERp u = actorofang->u(); + data->lastangdiff = u ? u->oangdiff : 0; + } } } } @@ -412,7 +428,10 @@ void so_restoreinterpolations(void) // Stick at end of drawscree for (i = 0, data = interp->data; i < interp->numinterpolations; i++, data++) if (data->curelement == soi_sprang) - data->actorofang->s().ang = data->bakipos; + { + auto actorofang = interp->data[i].actorofang; + if (actorofang) actorofang->s().ang = data->bakipos; + } else getvalue(*data, true) = data->bakipos; } diff --git a/source/games/sw/src/sprite.cpp b/source/games/sw/src/sprite.cpp index 894c71a30..b1b803736 100644 --- a/source/games/sw/src/sprite.cpp +++ b/source/games/sw/src/sprite.cpp @@ -630,7 +630,7 @@ void KillActor(DSWActor* actor) if (u) { PLAYERp pp; - short pnum; + int pnum; // doing a MissileSetPos - don't allow killing if (TEST(u->Flags, SPR_SET_POS_DONT_KILL)) @@ -645,7 +645,7 @@ void KillActor(DSWActor* actor) if (TEST(u->Flags, SPR_SO_ATTACHED)) { SECTOR_OBJECTp sop; - short sn, FoundSpriteNdx = -1; + int sn, FoundSpriteNdx = -1; for (sop = SectorObject; sop < &SectorObject[MAX_SECTOR_OBJECTS]; sop++) { @@ -672,8 +672,6 @@ void KillActor(DSWActor* actor) break; } } - - ASSERT(FoundSpriteNdx >= 0); } // if a player is dead and watching this sprite @@ -706,7 +704,7 @@ void KillActor(DSWActor* actor) if (TEST(sp->extra, SPRX_PLAYER_OR_ENEMY)) { USERp mu; - static short MissileStats[] = {STAT_MISSILE, STAT_MISSILE_SKIP4}; + static int8_t MissileStats[] = {STAT_MISSILE, STAT_MISSILE_SKIP4}; for (stat = 0; stat < SIZ(MissileStats); stat++) {