Files
felwell-core/ARGUSCORE_FIXES.md

155 lines
6.4 KiB
Markdown

# ArgusCore Fix Backlog
Tracks the incremental security/stability/correctness/blizzlike maintenance pass.
One fix per entry. See repo root workflow conventions for process rules.
Legend: `[ ]` open · `[WIP]` in progress · `[DONE]` shipped
---
## P0 — Security / Corruption
### [WIP] Core/Player - Vendor purchase quantity desync (validate-vs-deliver truncation)
**Subsystem:** Entities/Player, item vendor purchase
**Problem:** `Player::BuyItemFromVendorSlot(..., uint32 count, ...)` validates stock
limits, gold price, and extended-cost reagent/currency ownership against the full
client-supplied `count` (an `int32` read directly off `CMSG_BUY_ITEM`'s `Quantity`
field, widened to `uint32`). It then forwards `count` into
`Player::_StoreOrEquipNewItem(..., uint8 count, ...)`, which silently narrows it to
`count % 256`. Actual item delivery, reagent/currency consumption
(`DestroyItemCount`/`RemoveCurrency`), and vendor stock decrement
(`UpdateVendorItemCurrentCount`) all use the truncated value, while the "can you
afford/own this" checks earlier used the untruncated value. A single crafted packet
with `Quantity > 255` desyncs what was validated from what actually executes —
a client-triggerable economic integrity fault.
**Files:** `src/server/game/Entities/Player/Player.cpp`
(`BuyItemFromVendorSlot`, `_StoreOrEquipNewItem`),
`src/server/game/Handlers/ItemHandler.cpp` (`HandleBuyItemOpcode`)
**Reference:** None directly ported; DestinyCore keeps `count` as `uint8` end-to-end
(no widening, so no desync there). ArgusCore widened the outer function to `uint32`
without updating the inner one.
**Fix:** Clamp `count` to `uint8` range immediately after the existing
`if (count < 1) count = 1;` cheat guard in `BuyItemFromVendorSlot`, before any
validation runs, so every downstream check validates the exact quantity that will
be charged and delivered.
**Test:** See commit / manual test instructions below.
---
## P1 — Stability
### [ ] Core/Unit - TriggerAuraHeartbeat iterator invalidation
**Subsystem:** Entities/Unit, Spells/Auras
**Problem:** `Unit::TriggerAuraHeartbeat()` (`Unit.cpp:513-519`) iterates
`m_appliedAuras` (a `std::multimap`) with a plain range-based `for` while calling
`Aura::Heartbeat()`, which invokes arbitrary `AuraScript::OnHeartbeat` hooks. If a
heartbeat hook removes the aura currently being visited (a normal aura-scripting
pattern — "cancel self if condition no longer met"), `Unit::_UnapplyAura` erases
that exact map node mid-loop, which is undefined behavior for the range-for's
hidden iterator.
**Files:** `src/server/game/Entities/Unit/Unit.cpp`
**Reference:** Not present in DestinyCore (the heartbeat-aura mechanic is
Legion-specific). Fix is precedented in-tree: `Unit::AtEnterCombat()` /
`Unit::AtExitCombat()` (same file, ~line 8774) invoke the same class of arbitrary
aura-script hook over the same container using an erase-safe idiom (capture the
pointer, advance the iterator, *then* invoke the hook).
**Fix:** Convert `TriggerAuraHeartbeat`'s loop to the same erase-safe idiom already
used by `AtEnterCombat`/`AtExitCombat`.
**Status:** Not started — next in queue after the vendor purchase fix.
### [ ] Core/Vehicle - Null seat dereference in VehicleHandler
**Subsystem:** Handlers/VehicleHandler, Entities/Vehicle
**Problem:** `HandleRequestVehiclePrevSeat`, `HandleRequestVehicleNextSeat`,
`HandleMoveChangeVehicleSeats`, and `HandleRequestVehicleSwitchSeat`
(`VehicleHandler.cpp:45-113`) call `Vehicle::GetSeatForPassenger()`, which is
documented to return null if the passenger isn't currently seated, and dereference
the result without a null check (contrast `CombatHandler.cpp:51-52`, which at
least `ASSERT`s). A rapid double-send of a vehicle-seat opcode during a seat-change
race window is a plausible client-triggerable null deref.
**Files:** `src/server/game/Handlers/VehicleHandler.cpp`
**Reference:** Same missing check exists in DestinyCore — inherited from upstream
TrinityCore, not ArgusCore-specific. Lower priority than the heartbeat bug since
it's long-standing and shared across forks, but still a live crash bug.
**Status:** Not started.
### [ ] Core/Loot - Unguarded division in HandleLootMoneyOpcode
**Subsystem:** Handlers/LootHandler
**Problem:** `uint32 goldPerPlayer = uint32((loot->gold) / (playersNear.size()));`
(`LootHandler.cpp:~168`) has no guard against `playersNear` being empty. In normal
play the looter is always included, so this is low-exploitability today, but it's
an unguarded integer division on a client-triggerable path (`CMSG_LOOT_MONEY`).
**Files:** `src/server/game/Handlers/LootHandler.cpp`
**Reference:** Same pattern exists in DestinyCore; not ArgusCore-specific.
**Status:** Not started — low priority, defensive-only.
---
## P2 — Core Correctness
### [ ] Core/Bank - Slot/PackSlot argument order inconsistency
**Subsystem:** Handlers/BankHandler
**Problem:** `HandleAutoBankReagentOpcode` calls
`GetItemByPos(autoBankReagent.PackSlot, autoBankReagent.Slot)` while
`HandleAutoStoreBankReagentOpcode` calls
`GetItemByPos(autoStoreBankReagent.Slot, autoStoreBankReagent.PackSlot)` — reversed
argument order relative to its sibling. Each packet's `Read()` implementation reads
the two fields in different wire order, so this may be self-consistent and not an
actual bug — needs verification against a real client packet capture before
touching it.
**Files:** `src/server/game/Handlers/BankHandler.cpp`
**Status:** Needs verification, not confirmed as a bug. Low priority.
---
## P3 — Blizzlike Gameplay
(Not populated by this pass — see `ROADMAP.md` / `plans/00-arguscore-analysis-and-roadmap.md`
for the active class-spell-porting and content workstreams, which are tracked
separately from this security/stability backlog.)
---
## P4 — Performance / Cleanup
(Not populated by this pass.)
---
## Notes on scope
This backlog is deliberately shallow on first pass — it reflects two targeted,
read-only audits (item/gold/trade exploit surface; crash/stability surface) rather
than an exhaustive line-by-line review. Areas checked and found solidly guarded
during this pass (not re-audited unless something changes nearby): `TradeHandler`,
`MailHandler` (including mail money/COD overflow guards), `AuctionHouseHandler`,
`GuildHandler`/`Guild.cpp` bank-item moves, `VoidStorageHandler`, movement/teleport
coordinate validation (`MovementHandler.cpp`, `ValidateMovementInfo`), `Spell.cpp`/
`SpellEffects.cpp` target-pointer handling, `LootHandler.cpp` target/master-loot
lookups, `Group.cpp` aura/member iteration.