From 8607a7fb338d81a3e5692d1aafd0951e7fd603c5 Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Sat, 17 Aug 2024 18:19:22 +0200 Subject: [PATCH] Fixes UB in Cmd_averagestats (#5191) * Fixes UB in Cmd_averagestats * fix test and align default case --- src/battle_script_commands.c | 23 ++++++++++++++++------- test/battle/move_effect/guard_split.c | 22 ++++++++++++++++++++++ test/battle/move_effect/power_split.c | 22 ++++++++++++++++++++++ 3 files changed, 60 insertions(+), 7 deletions(-) create mode 100644 test/battle/move_effect/guard_split.c create mode 100644 test/battle/move_effect/power_split.c diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 394a455b3a..9165d7b7e4 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -15669,17 +15669,26 @@ static void Cmd_swapstatstages(void) gBattlescriptCurrInstr = cmd->nextInstr; } +static u16 *GetBattlerStat(struct BattlePokemon *battler, u32 stat) +{ + switch (stat) + { + case STAT_ATK: return &battler->attack; + case STAT_DEF: return &battler->defense; + case STAT_SPATK: return &battler->spAttack; + case STAT_SPDEF: return &battler->spDefense; + default: return NULL; + } +} + static void Cmd_averagestats(void) { CMD_ARGS(u8 stat); - u8 stat = cmd->stat; - u16 atkStat = *(u16 *)((&gBattleMons[gBattlerAttacker].attack) + (stat - 1)); - u16 defStat = *(u16 *)((&gBattleMons[gBattlerTarget].attack) + (stat - 1)); - u16 average = (atkStat + defStat) / 2; - - *(u16 *)((&gBattleMons[gBattlerAttacker].attack) + (stat - 1)) = average; - *(u16 *)((&gBattleMons[gBattlerTarget].attack) + (stat - 1)) = average; + u16 *stat1 = GetBattlerStat(&gBattleMons[gBattlerAttacker], cmd->stat); + u16 *stat2 = GetBattlerStat(&gBattleMons[gBattlerTarget], cmd->stat); + u16 avg = (*stat1 + *stat2) / 2; + *stat1 = *stat2 = avg; gBattlescriptCurrInstr = cmd->nextInstr; } diff --git a/test/battle/move_effect/guard_split.c b/test/battle/move_effect/guard_split.c new file mode 100644 index 0000000000..3f012ab6e2 --- /dev/null +++ b/test/battle/move_effect/guard_split.c @@ -0,0 +1,22 @@ +#include "global.h" +#include "test/battle.h" + +ASSUMPTIONS +{ + ASSUME(gMovesInfo[MOVE_GUARD_SPLIT].effect == EFFECT_GUARD_SPLIT); +} + +SINGLE_BATTLE_TEST("Guard Split averages users and targets Def and Sp. Def stats") +{ + GIVEN { + PLAYER(SPECIES_BULBASAUR); + OPPONENT(SPECIES_IVYSAUR); + } WHEN { + TURN { MOVE(player, MOVE_GUARD_SPLIT); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_GUARD_SPLIT, player); + } THEN { + EXPECT_EQ(player->defense, opponent->defense); + EXPECT_EQ(player->spDefense, opponent->spDefense); + } +} diff --git a/test/battle/move_effect/power_split.c b/test/battle/move_effect/power_split.c new file mode 100644 index 0000000000..70d1bfd5ea --- /dev/null +++ b/test/battle/move_effect/power_split.c @@ -0,0 +1,22 @@ +#include "global.h" +#include "test/battle.h" + +ASSUMPTIONS +{ + ASSUME(gMovesInfo[MOVE_POWER_SPLIT].effect == EFFECT_POWER_SPLIT); +} + +SINGLE_BATTLE_TEST("Power Split averages user and targets Atk and Sp. Atk stats") +{ + GIVEN { + PLAYER(SPECIES_BULBASAUR); + OPPONENT(SPECIES_IVYSAUR); + } WHEN { + TURN { MOVE(player, MOVE_POWER_SPLIT); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_POWER_SPLIT, player); + } THEN { + EXPECT_EQ(player->attack, opponent->attack); + EXPECT_EQ(player->spAttack, opponent->spAttack); + } +}