Resolved Issue #309 by Detecting Overflows & Underflows in Set Instructions to p->itemAmount and p->backupItemAmount

This commit is contained in:
SpringEThing 2025-10-16 03:58:08 +01:00 committed by Eidolon
parent 15413bf6d0
commit 2ddc4c4867
8 changed files with 93 additions and 65 deletions

View file

@ -6090,7 +6090,7 @@ static void Got_Cheat(const UINT8 **cp, INT32 playernum)
K_StopRoulette(&player->itemRoulette);
player->itemtype = item;
player->itemamount = amt;
K_SetPlayerItemAmount(player, amt);
if (amt == 0)
{

View file

@ -2685,7 +2685,7 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
// SRB2kart
p->itemtype = itemtype;
p->itemamount = itemamount;
K_SetPlayerItemAmount(p, itemamount);
p->growshrinktimer = growshrinktimer;
p->karmadelay = 0;
p->eggmanblame = -1;

View file

@ -72,6 +72,28 @@
// comeback is Battle Mode's karma comeback, also bool
// mapreset is set when enough players fill an empty server
UINT8 K_SetPlayerItemAmount(player_t *player, UINT8 amount)
{
player->itemamount = max(min(UINT8_MAX, amount), 0);
return player->itemamount;
}
UINT8 K_SetPlayerBackupItemAmount(player_t *player, UINT8 amount)
{
player->backupitemamount = max(min(UINT8_MAX, amount), 0);
return player->backupitemamount;
}
UINT8 K_AdjustPlayerItemAmount(player_t *player, SINT8 amount)
{
return K_SetPlayerItemAmount(player, player->itemamount + amount);
}
UINT8 K_AdjustPlayerBackupItemAmount(player_t *player, SINT8 amount)
{
return K_SetPlayerBackupItemAmount(player, player->backupitemamount + amount);
}
void K_PopBubbleShield(player_t *player)
{
if (player->curshield != KSHIELD_BUBBLE)
@ -81,7 +103,7 @@ void K_PopBubbleShield(player_t *player)
player->curshield = KSHIELD_NONE;
player->itemtype = 0;
player->itemamount = 0;
K_SetPlayerItemAmount(player, 0);
player->itemflags &= ~(IF_ITEMOUT|IF_EGGMANOUT);
K_AddHitLag(player->mo, 4, false);
@ -7698,7 +7720,7 @@ void K_PuntMine(mobj_t *origMine, mobj_t *punter)
if (mineOwner->player->itemamount)
{
mineOwner->player->itemamount--;
K_AdjustPlayerItemAmount(mineOwner->player, -1);
}
if (!mineOwner->player->itemamount)
@ -8268,7 +8290,7 @@ void K_PopPlayerShield(player_t *player)
player->curshield = KSHIELD_NONE;
player->itemtype = KITEM_NONE;
player->itemamount = 0;
K_SetPlayerItemAmount(player, 0);
K_UnsetItemOut(player);
}
@ -8516,9 +8538,9 @@ void K_DropHnextList(player_t *player)
player->itemflags &= ~IF_EGGMANOUT;
}
else if ((player->itemflags & IF_ITEMOUT)
&& (dropall || (--player->itemamount <= 0)))
&& (dropall || (K_AdjustPlayerItemAmount(player, -1) <= 0)))
{
player->itemamount = 0;
K_SetPlayerItemAmount(player, 0);
K_UnsetItemOut(player);
player->itemtype = KITEM_NONE;
}
@ -8773,7 +8795,7 @@ void K_RepairOrbitChain(mobj_t *orbit)
}
if (orbit->target && !P_MobjWasRemoved(orbit->target) && orbit->target->player->itemamount != num)
orbit->target->player->itemamount = num;
K_SetPlayerItemAmount(orbit->target->player, num);
}
}
@ -8926,7 +8948,7 @@ static void K_MoveHeldObjects(player_t *player)
}
else if (player->itemflags & IF_ITEMOUT)
{
player->itemamount = 0;
K_SetPlayerItemAmount(player, 0);
K_UnsetItemOut(player);
player->itemtype = KITEM_NONE;
}
@ -8945,7 +8967,7 @@ static void K_MoveHeldObjects(player_t *player)
}
else if (player->itemflags & IF_ITEMOUT)
{
player->itemamount = 0;
K_SetPlayerItemAmount(player, 0);
K_UnsetItemOut(player);
player->itemtype = KITEM_NONE;
}
@ -9173,10 +9195,10 @@ static void K_TryMoveBackupItem(player_t *player)
{
if (player->itemtype && player->itemtype == player->backupitemtype && !(player->itemflags & IF_ITEMOUT))
{
player->itemamount += player->backupitemamount;
K_AdjustPlayerItemAmount(player, player->backupitemamount);
player->backupitemtype = 0;
player->backupitemamount = 0;
K_SetPlayerBackupItemAmount(player, 0);
S_StartSound(player->mo, sfx_mbs54);
}
@ -9184,10 +9206,10 @@ static void K_TryMoveBackupItem(player_t *player)
if (player->itemtype == KITEM_NONE && player->backupitemtype && P_CanPickupItem(player, PICKUP_PAPERITEM))
{
player->itemtype = player->backupitemtype;
player->itemamount = player->backupitemamount;
K_SetPlayerItemAmount(player, player->backupitemamount);
player->backupitemtype = 0;
player->backupitemamount = 0;
K_SetPlayerBackupItemAmount(player, 0);
S_StartSound(player->mo, sfx_mbs54);
}
@ -10412,7 +10434,7 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd)
{
player->rings = 0;
player->itemtype = 0;
player->itemamount = 0;
K_SetPlayerItemAmount(player, 0);
player->itemRoulette.active = false;
}
}
@ -10961,7 +10983,7 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd)
K_DeleteHnextList(player);
K_DropItems(player);
player->itemamount = 0;
K_SetPlayerItemAmount(player, 0);
player->itemtype = 0;
player->rocketsneakertimer = 0;
@ -10969,7 +10991,7 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd)
if (player->itemamount)
{
K_DropPaperItem(player, player->itemtype, player->itemamount);
player->itemtype = player->itemamount = 0;
player->itemtype = K_SetPlayerItemAmount(player, 0);
}
*/
@ -11616,7 +11638,7 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd)
// activate a mine while you're out of its radius,
// the SAME tic it sets your itemamount to 0
// ...:dumbestass:
player->itemamount--;
K_AdjustPlayerItemAmount(player, -1);
K_PlayAttackTaunt(player->mo);
player->botvars.itemconfirm = 0;
}
@ -13687,11 +13709,11 @@ void K_StripItems(player_t *player)
K_DropRocketSneaker(player);
K_DropKitchenSink(player);
player->itemtype = KITEM_NONE;
player->itemamount = 0;
K_SetPlayerItemAmount(player, 0);
player->itemflags &= ~(IF_ITEMOUT|IF_EGGMANOUT);
player->backupitemtype = KITEM_NONE;
player->backupitemamount = 0;
K_SetPlayerBackupItemAmount(player, 0);
if (player->itemRoulette.eggman == false)
{
@ -15264,7 +15286,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
{
K_DoSneaker(player, 1);
K_PlayBoostTaunt(player->mo);
player->itemamount--;
K_AdjustPlayerItemAmount(player, -1);
player->botvars.itemconfirm = 0;
}
break;
@ -15282,7 +15304,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
//K_DoSneaker(player, 2);
player->rocketsneakertimer = (itemtime*3);
player->itemamount--;
K_AdjustPlayerItemAmount(player, -1);
K_UpdateHnextList(player, true);
for (moloop = 0; moloop < 2; moloop++)
@ -15313,7 +15335,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
max(7u * TICRATE + behindScaled, player->invincibilitytimer + 5u*TICRATE));
K_PlayPowerGloatSound(player->mo);
player->itemamount--;
K_AdjustPlayerItemAmount(player, -1);
player->botvars.itemconfirm = 0;
}
break;
@ -15333,7 +15355,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
mo = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_BANANA_SHIELD);
if (!mo)
{
player->itemamount = moloop;
K_SetPlayerItemAmount(player, moloop);
break;
}
mo->flags |= MF_NOCLIPTHING;
@ -15350,7 +15372,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
}
else if (ATTACK_IS_DOWN && (player->itemflags & IF_ITEMOUT)) // Banana x3 thrown
{
player->itemamount--;
K_AdjustPlayerItemAmount(player, -1);
K_ThrowKartItem(player, false, MT_BANANA, -1, 0, 0);
K_PlayAttackTaunt(player->mo);
K_UpdateHnextList(player, false);
@ -15361,7 +15383,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO)
{
mobj_t *mo;
player->itemamount--;
K_AdjustPlayerItemAmount(player, -1);
player->itemflags |= IF_EGGMANOUT;
S_StartSound(player->mo, sfx_s254);
mo = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_EGGMANITEM_SHIELD);
@ -15397,7 +15419,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
mo = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_ORBINAUT_SHIELD);
if (!mo)
{
player->itemamount = moloop;
K_SetPlayerItemAmount(player, moloop);
break;
}
mo->flags |= MF_NOCLIPTHING;
@ -15416,7 +15438,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
}
else if (ATTACK_IS_DOWN && (player->itemflags & IF_ITEMOUT)) // Orbinaut x3 thrown
{
player->itemamount--;
K_AdjustPlayerItemAmount(player, -1);
K_ThrowKartItem(player, true, MT_ORBINAUT, 1, 0, 0);
K_PlayAttackTaunt(player->mo);
K_UpdateHnextList(player, false);
@ -15441,7 +15463,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
mo = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_JAWZ_SHIELD);
if (!mo)
{
player->itemamount = moloop;
K_SetPlayerItemAmount(player, moloop);
break;
}
mo->flags |= MF_NOCLIPTHING;
@ -15459,7 +15481,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
}
else if (ATTACK_IS_DOWN && HOLDING_ITEM && (player->itemflags & IF_ITEMOUT)) // Jawz thrown
{
player->itemamount--;
K_AdjustPlayerItemAmount(player, -1);
K_ThrowKartItem(player, true, MT_JAWZ, 1, 0, 0);
K_PlayAttackTaunt(player->mo);
K_UpdateHnextList(player, false);
@ -15487,7 +15509,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
}
else if (ATTACK_IS_DOWN && (player->itemflags & IF_ITEMOUT))
{
player->itemamount--;
K_AdjustPlayerItemAmount(player, -1);
K_ThrowKartItem(player, false, MT_SSMINE, 1, 1, 0);
K_PlayAttackTaunt(player->mo);
player->itemflags &= ~IF_ITEMOUT;
@ -15498,7 +15520,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
case KITEM_LANDMINE:
if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO)
{
player->itemamount--;
K_AdjustPlayerItemAmount(player, -1);
if (player->throwdir > 0)
{
K_ThrowKartItem(player, true, MT_LANDMINE, -1, 0, 0);
@ -15533,7 +15555,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
}
else if (ATTACK_IS_DOWN && (player->itemflags & IF_ITEMOUT))
{
player->itemamount--;
K_AdjustPlayerItemAmount(player, -1);
mobj_t *drop = K_ThrowKartItem(player, (player->throwdir > 0), MT_DROPTARGET, -1, 0, 0);
P_SetTarget(&drop->tracer, player->mo);
K_PlayAttackTaunt(player->mo);
@ -15631,8 +15653,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
P_SetObjectMomZ(player->mo, -50*FRACUNIT, true);
}
*/
player->itemamount = 0;
K_SetPlayerItemAmount(player, 0);
player->botvars.itemconfirm = 0;
player->ballhogcharge = 0;
player->ballhogburst = 0;
@ -15647,8 +15668,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
if (numhogs > 0) // no tapfire scams
{
K_SetItemOut(player); // need this to set itemscale
player->itemamount -= numhogs;
K_AdjustPlayerItemAmount(player, -numhogs);
K_PlayAttackTaunt(player->mo);
K_DoBallhogAttack(player, numhogs);
@ -15678,7 +15698,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
case KITEM_SPB:
if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO)
{
player->itemamount--;
K_AdjustPlayerItemAmount(player, -1);
K_SetItemOut(player);
K_ThrowKartItem(player, true, MT_SPB, 1, 0, 0);
K_UnsetItemOut(player);
@ -15718,7 +15738,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
S_StartSound(player->mo, sfx_kc5a);
player->itemamount--;
K_AdjustPlayerItemAmount(player, -1);
player->botvars.itemconfirm = 0;
}
break;
@ -15726,7 +15746,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO)
{
K_DoShrink(player);
player->itemamount--;
K_AdjustPlayerItemAmount(player, -1);
K_PlayPowerGloatSound(player->mo);
player->botvars.itemconfirm = 0;
}
@ -15841,7 +15861,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
if (player->bubbleblowup > bubbletime*2)
{
player->itemamount--;
K_AdjustPlayerItemAmount(player, -1);
if (player->throwdir == -1)
{
@ -15947,7 +15967,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
player->flamemeter = 0;
player->flamelength = 0;
player->itemflags &= ~IF_HOLDREADY;
player->itemamount--;
K_AdjustPlayerItemAmount(player, -1);
}
}
else
@ -15981,7 +16001,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
case KITEM_HYUDORO:
if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO)
{
player->itemamount--;
K_AdjustPlayerItemAmount(player, -1);
//K_DoHyudoroSteal(player); // yes. yes they do.
Obj_HyudoroDeploy(player->mo);
K_PlayAttackTaunt(player->mo);
@ -15994,7 +16014,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
K_PlayBoostTaunt(player->mo);
//K_DoPogoSpring(player->mo, 32<<FRACBITS, 2);
P_SpawnMobjFromMobj(player->mo, 0, 0, 0, MT_POGOSPRING);
player->itemamount--;
K_AdjustPlayerItemAmount(player, -1);
player->botvars.itemconfirm = 0;
}
break;
@ -16037,7 +16057,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
// player->strongdriftboost += TICRATE;
// player->driftboost += TICRATE;
K_AwardPlayerRings(player, 20*player->itemamount, true);
player->itemamount = 0;
K_SetPlayerItemAmount(player, 0);
player->botvars.itemconfirm = 0;
}
break;
@ -16062,7 +16082,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
}
else if (ATTACK_IS_DOWN && HOLDING_ITEM && (player->itemflags & IF_ITEMOUT)) // Sink thrown
{
player->itemamount--;
K_AdjustPlayerItemAmount(player, -1);
K_ThrowKartItem(player, false, MT_SINK, 1, 2, 0);
K_PlayAttackTaunt(player->mo);
player->itemflags &= ~IF_ITEMOUT;
@ -16073,7 +16093,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
case KITEM_GACHABOM:
if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO)
{
player->itemamount--;
K_AdjustPlayerItemAmount(player, -1);
K_SetItemOut(player); // need this to set itemscale
K_ThrowKartItem(player, true, MT_GACHABOM, 0, 0, 0);
K_UnsetItemOut(player);
@ -16111,7 +16131,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
K_UnsetItemOut(player);
}
player->itemamount--;
K_AdjustPlayerItemAmount(player, -1);
K_PlayAttackTaunt(player->mo);
K_UpdateHnextList(player, false);
player->botvars.itemconfirm = 0;
@ -16127,7 +16147,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
K_UnsetItemOut(player);
player->itemamount--;
K_AdjustPlayerItemAmount(player, -1);
K_PlayAttackTaunt(player->mo);
player->botvars.itemconfirm = 0;
}
@ -16137,7 +16157,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
&& !player->sadtimer)
{
player->sadtimer = stealtime;
player->itemamount--;
K_AdjustPlayerItemAmount(player, -1);
player->botvars.itemconfirm = 0;
}
break;
@ -17553,20 +17573,20 @@ static boolean K_PickUp(player_t *player, mobj_t *picked)
if (player->itemtype == type && player->itemamount && !(player->itemflags & IF_ITEMOUT))
{
// We have this item in main slot but not deployed, just add it
player->itemamount += amount;
K_SetPlayerItemAmount(player, player->itemamount + amount);
}
else if (player->backupitemamount && player->backupitemtype)
{
// We already have a backup item, stack it if it can be stacked or discard it
if (player->backupitemtype == type)
{
player->backupitemamount += amount;
K_AdjustPlayerBackupItemAmount(player, amount);
}
else
{
K_DropPaperItem(player, player->backupitemtype, player->backupitemamount);
player->backupitemtype = type;
player->backupitemamount = amount;
K_SetPlayerBackupItemAmount(player, amount);
S_StartSound(player->mo, sfx_kc65);
}
}
@ -17574,7 +17594,7 @@ static boolean K_PickUp(player_t *player, mobj_t *picked)
{
// We have no backup item, load one up
player->backupitemtype = type;
player->backupitemamount = amount;
K_SetPlayerBackupItemAmount(player, amount);
}
S_StartSound(player->mo, sfx_aple);

View file

@ -125,6 +125,11 @@ Make sure this matches the actual number of states
#define AUTORESPAWN_TIME (10*TICRATE)
#define AUTORESPAWN_THRESHOLD (7*TICRATE)
UINT8 K_SetPlayerItemAmount(player_t *player, UINT8 amount);
UINT8 K_SetPlayerBackupItemAmount(player_t *player, UINT8 amount);
UINT8 K_AdjustPlayerItemAmount(player_t *player, SINT8 amount);
UINT8 K_AdjustPlayerBackupItemAmount(player_t *player, SINT8 amount);
angle_t K_ReflectAngle(angle_t angle, angle_t against, fixed_t maxspeed, fixed_t yourspeed);
void K_PopBubbleShield(player_t *player);

View file

@ -1956,7 +1956,8 @@ void K_KartGetItemResult(player_t *const player, kartitems_t getitem)
UINT8 itemamount = K_ItemResultToAmount(getitem, &player->itemRoulette);
if (cv_kartdebugitem.value != KITEM_NONE && cv_kartdebugitem.value == player->itemtype && cv_kartdebugamount.value > 1)
itemamount = cv_kartdebugamount.value;
player->itemamount = itemamount;
K_SetPlayerItemAmount(player, itemamount);
if (player->itemtype == KITEM_SPB)
Obj_SPBEradicateCapsules();

View file

@ -19,6 +19,7 @@
#include "../r_main.h"
#include "../tables.h"
#include "../s_sound.h"
#include "../k_kart.h"
/* An object may not be visible on the same tic:
1) that it spawned
@ -85,7 +86,7 @@ bool award_target(mobj_t* mobj)
if (rebound_timer(mobj) < 1)
{
player->itemtype = KITEM_GACHABOM;
player->itemamount++;
K_AdjustPlayerItemAmount(player, 1);
if (player->roundconditions.gachabom_miser == 1)
player->roundconditions.gachabom_miser = 0;

View file

@ -612,7 +612,7 @@ Obj_GardenTopThrow (player_t *player)
}
if (player->itemamount > 0)
player->itemamount--;
K_AdjustPlayerItemAmount(player, -1);
if (player->itemamount <= 0)
player->itemtype = KITEM_NONE;

View file

@ -463,9 +463,9 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
player->itemtype = special->threshold;
if ((UINT16)(player->itemamount) + special->movecount > 255)
player->itemamount = 255;
K_SetPlayerItemAmount(player, 255);
else
player->itemamount += special->movecount;
K_AdjustPlayerItemAmount(player, special->movecount);
}
}
@ -1800,16 +1800,17 @@ void P_UpdateRemovedOrbital(mobj_t *target, mobj_t *inflictor, mobj_t *source)
{
if (target->target->hnext && !P_MobjWasRemoved(target->target->hnext))
K_KillBananaChain(target->target->hnext, inflictor, source);
target->target->player->itemamount = 0;
K_SetPlayerItemAmount(target->target->player, 0);
}
else if (target->target->player->itemamount)
target->target->player->itemamount--;
K_AdjustPlayerItemAmount(target->target->player, -1);
}
else if ((target->type == MT_ORBINAUT_SHIELD && target->target->player->itemtype == KITEM_ORBINAUT) // orbit items
|| (target->type == MT_JAWZ_SHIELD && target->target->player->itemtype == KITEM_JAWZ))
{
if (target->target->player->itemamount)
target->target->player->itemamount--;
K_AdjustPlayerItemAmount(target->target->player, -1);
if (target->lastlook != 0)
{
K_RepairOrbitChain(target);
@ -2206,15 +2207,15 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
if (target->threshold < 1 || target->threshold >= NUMKARTITEMS) // bruh moment prevention
{
player->itemtype = KITEM_SAD;
player->itemamount = 1;
K_SetPlayerItemAmount(player, 1);
}
else
{
player->itemtype = target->threshold;
if (K_GetShieldFromItem(player->itemtype) != KSHIELD_NONE) // never give more than 1 shield
player->itemamount = 1;
K_SetPlayerItemAmount(player, 1);
else
player->itemamount = max(1, target->movecount);
K_SetPlayerItemAmount(player, max(1, target->movecount));
}
player->karthud[khud_itemblink] = TICRATE;
player->karthud[khud_itemblinkmode] = 0;