- do better owner checks in weapon code.

Due to poor data clearing logic there is a chance that the owner of a sprite is 0 if invalid, but this code never properly checked all conditions before accessing the owner's user's ID.
This commit is contained in:
Christoph Oelckers 2021-11-15 20:57:09 +01:00
parent cb31127df5
commit e2e697e9bb
3 changed files with 19 additions and 8 deletions

View file

@ -1234,6 +1234,7 @@ void RipperHatch(DSWActor* actor)
auto actorNew = InsertActor(wp->sectnum, STAT_DEFAULT); auto actorNew = InsertActor(wp->sectnum, STAT_DEFAULT);
np = &actorNew->s(); np = &actorNew->s();
np->clear(); np->clear();
ClearOwner(actorNew);
np->sectnum = wp->sectnum; np->sectnum = wp->sectnum;
np->statnum = STAT_DEFAULT; np->statnum = STAT_DEFAULT;
np->x = wp->x; np->x = wp->x;

View file

@ -1244,6 +1244,7 @@ void Ripper2Hatch(DSWActor* actor)
auto actorNew = InsertActor(wp->sectnum, STAT_DEFAULT); auto actorNew = InsertActor(wp->sectnum, STAT_DEFAULT);
np = &actorNew->s(); np = &actorNew->s();
np->clear(); np->clear();
ClearOwner(actorNew);
np->sectnum = wp->sectnum; np->sectnum = wp->sectnum;
np->statnum = STAT_DEFAULT; np->statnum = STAT_DEFAULT;
np->x = wp->x; np->x = wp->x;

View file

@ -5826,6 +5826,15 @@ objects.
*/ */
// this was done wrong multiple times below, resulting in spurious crashes.
bool OwnerIs(DSWActor* actor, int pic)
{
auto Own = GetOwner(actor);
if (Own == nullptr || !Own->hasU()) return false;
return Own->u()->ID == pic;
}
int int
DoDamage(short SpriteNum, short Weapon) DoDamage(short SpriteNum, short Weapon)
{ {
@ -6857,7 +6866,7 @@ DoDamage(short SpriteNum, short Weapon)
else else
{ {
// Don't let it hurt the SUMO // Don't let it hurt the SUMO
if (wp->owner >=0 && User[wp->owner].Data() && User[wp->owner]->ID == SUMO_RUN_R0) break; // JBF: added sanity check for wp->owner and User[wp->owner] if (OwnerIs(weapActor, SUMO_RUN_R0)) break;
ActorHealth(SpriteNum, damage); ActorHealth(SpriteNum, damage);
ActorPain(SpriteNum); ActorPain(SpriteNum);
ActorDamageSlide(SpriteNum, damage, ANG2SPRITE(sp, wp)); ActorDamageSlide(SpriteNum, damage, ANG2SPRITE(sp, wp));
@ -6901,7 +6910,7 @@ DoDamage(short SpriteNum, short Weapon)
case MINE_EXP: case MINE_EXP:
damage = GetDamage(SpriteNum, Weapon, DMG_MINE_EXP); damage = GetDamage(SpriteNum, Weapon, DMG_MINE_EXP);
if (wp->owner >= 0 && User[wp->owner].Data() && User[wp->owner]->ID == SERP_RUN_R0) if (OwnerIs(weapActor, SERP_RUN_R0))
{ {
damage /= 6; damage /= 6;
} }
@ -6928,9 +6937,9 @@ DoDamage(short SpriteNum, short Weapon)
if (wp->owner >= 0) if (wp->owner >= 0)
{ {
// Don't let serp skulls hurt the Serpent God // Don't let serp skulls hurt the Serpent God
if (User[wp->owner]->ID == SERP_RUN_R0) break; if (OwnerIs(weapActor, SERP_RUN_R0)) break;
// Don't let it hurt the SUMO // Don't let it hurt the SUMO
if (User[wp->owner]->ID == SUMO_RUN_R0) break; if (OwnerIs(weapActor, SUMO_RUN_R0)) break;
} }
if (u->ID == TRASHCAN) if (u->ID == TRASHCAN)
ActorHealth(SpriteNum, -500); ActorHealth(SpriteNum, -500);
@ -6981,8 +6990,8 @@ DoDamage(short SpriteNum, short Weapon)
damage = GetDamage(SpriteNum, Weapon, DMG_NAPALM_EXP); damage = GetDamage(SpriteNum, Weapon, DMG_NAPALM_EXP);
// Sumo Nap does less // Sumo Nap does less
if (wp->owner >= 0 && User[wp->owner].Data() && User[wp->owner]->ID == SUMO_RUN_R0) if (OwnerIs(weapActor, SUMO_RUN_R0))
damage /= 4; damage /= 4;
if (u->sop_parent) if (u->sop_parent)
{ {
@ -7004,7 +7013,7 @@ DoDamage(short SpriteNum, short Weapon)
else else
{ {
// Don't let it hurt the SUMO // Don't let it hurt the SUMO
if (User[wp->owner]->ID == SUMO_RUN_R0) break; if (OwnerIs(weapActor, SUMO_RUN_R0)) break;
ActorHealth(SpriteNum, damage); ActorHealth(SpriteNum, damage);
ActorChooseDeath(SpriteNum, Weapon); ActorChooseDeath(SpriteNum, Weapon);
} }
@ -7217,7 +7226,7 @@ DoDamage(short SpriteNum, short Weapon)
else else
{ {
// Don't let it hurt the SUMO // Don't let it hurt the SUMO
if (wp->owner >= 0 && User[wp->owner]->ID == SUMO_RUN_R0) break; // JBF: added owner check if (OwnerIs(weapActor, SUMO_RUN_R0)) break;
ActorHealth(SpriteNum, damage); ActorHealth(SpriteNum, damage);
ActorPain(SpriteNum); ActorPain(SpriteNum);
ActorChooseDeath(SpriteNum, Weapon); ActorChooseDeath(SpriteNum, Weapon);