fix: migrate 197 unsafe packet bounds checks to hasRemaining/getRemainingSize

All domain handler files used 'packet.getSize() - packet.getReadPos()'
which underflows to ~2^64 when readPos exceeds size (documented in
commit ed63b029). The game_handler.cpp and packet_parsers were migrated
to hasRemaining(N) in an earlier cleanup, but the domain handlers were
created after that migration by the PR #23 split, copying the old
unsafe patterns back in. Now uses hasRemaining(N) for comparisons and
getRemainingSize() for assignments across all 7 handler files.
This commit is contained in:
Kelsi 2026-03-29 20:53:26 -07:00
parent 849542d01d
commit 294c91d84a
7 changed files with 197 additions and 197 deletions

View file

@ -27,7 +27,7 @@ void ChatHandler::registerOpcodes(DispatchTable& table) {
};
table[Opcode::SMSG_EMOTE] = [this](network::Packet& packet) {
if (owner_.getState() != WorldState::IN_WORLD) return;
if (packet.getSize() - packet.getReadPos() < 12) return;
if (!packet.hasRemaining(12)) return;
uint32_t emoteAnim = packet.readUInt32();
uint64_t sourceGuid = packet.readUInt64();
if (owner_.emoteAnimCallback_ && sourceGuid != 0)

View file

@ -33,9 +33,9 @@ void CombatHandler::registerOpcodes(DispatchTable& table) {
if (owner_.addonEventCallback_) owner_.addonEventCallback_("UNIT_THREAT_LIST_UPDATE", {});
};
table[Opcode::SMSG_THREAT_REMOVE] = [this](network::Packet& packet) {
if (packet.getSize() - packet.getReadPos() < 1) return;
if (!packet.hasRemaining(1)) return;
uint64_t unitGuid = packet.readPackedGuid();
if (packet.getSize() - packet.getReadPos() < 1) return;
if (!packet.hasRemaining(1)) return;
uint64_t victimGuid = packet.readPackedGuid();
auto it = threatLists_.find(unitGuid);
if (it != threatLists_.end()) {
@ -92,7 +92,7 @@ void CombatHandler::registerOpcodes(DispatchTable& table) {
};
table[Opcode::SMSG_ATTACKERSTATEUPDATE] = [this](network::Packet& packet) { handleAttackerStateUpdate(packet); };
table[Opcode::SMSG_AI_REACTION] = [this](network::Packet& packet) {
if (packet.getSize() - packet.getReadPos() < 12) return;
if (!packet.hasRemaining(12)) return;
uint64_t guid = packet.readUInt64();
uint32_t reaction = packet.readUInt32();
if (reaction == 2 && owner_.npcAggroCallback_) {
@ -108,7 +108,7 @@ void CombatHandler::registerOpcodes(DispatchTable& table) {
table[Opcode::SMSG_ENVIRONMENTAL_DAMAGE_LOG] = [this](network::Packet& packet) {
// uint64 victimGuid + uint8 envDmgType + uint32 damage + uint32 absorbed + uint32 resisted
// envDmgType: 0=Exhausted(fatigue), 1=Drowning, 2=Fall, 3=Lava, 4=Slime, 5=Fire
if (packet.getSize() - packet.getReadPos() < 21) { packet.setReadPos(packet.getSize()); return; }
if (!packet.hasRemaining(21)) { packet.setReadPos(packet.getSize()); return; }
uint64_t victimGuid = packet.readUInt64();
uint8_t envType = packet.readUInt8();
uint32_t dmg = packet.readUInt32();
@ -133,20 +133,20 @@ void CombatHandler::registerOpcodes(DispatchTable& table) {
// Both packets share the same format:
// packed_guid (unit) + packed_guid (highest-threat target or target, unused here)
// + uint32 count + count × (packed_guid victim + uint32 threat)
if (packet.getSize() - packet.getReadPos() < 1) return;
if (!packet.hasRemaining(1)) return;
uint64_t unitGuid = packet.readPackedGuid();
if (packet.getSize() - packet.getReadPos() < 1) return;
if (!packet.hasRemaining(1)) return;
(void)packet.readPackedGuid(); // highest-threat / current target
if (packet.getSize() - packet.getReadPos() < 4) return;
if (!packet.hasRemaining(4)) return;
uint32_t cnt = packet.readUInt32();
if (cnt > 100) { packet.setReadPos(packet.getSize()); return; } // sanity
std::vector<ThreatEntry> list;
list.reserve(cnt);
for (uint32_t i = 0; i < cnt; ++i) {
if (packet.getSize() - packet.getReadPos() < 1) return;
if (!packet.hasRemaining(1)) return;
ThreatEntry entry;
entry.victimGuid = packet.readPackedGuid();
if (packet.getSize() - packet.getReadPos() < 4) return;
if (!packet.hasRemaining(4)) return;
entry.threat = packet.readUInt32();
list.push_back(entry);
}
@ -558,7 +558,7 @@ void CombatHandler::handleSpellHealLog(network::Packet& packet) {
}
void CombatHandler::handleSetForcedReactions(network::Packet& packet) {
if (packet.getSize() - packet.getReadPos() < 4) return;
if (!packet.hasRemaining(4)) return;
uint32_t count = packet.readUInt32();
if (count > 64) {
LOG_WARNING("SMSG_SET_FORCED_REACTIONS: suspicious count ", count, ", ignoring");
@ -567,7 +567,7 @@ void CombatHandler::handleSetForcedReactions(network::Packet& packet) {
}
forcedReactions_.clear();
for (uint32_t i = 0; i < count; ++i) {
if (packet.getSize() - packet.getReadPos() < 8) break;
if (!packet.hasRemaining(8)) break;
uint32_t factionId = packet.readUInt32();
uint32_t reaction = packet.readUInt32();
forcedReactions_[factionId] = static_cast<uint8_t>(reaction);

View file

@ -40,20 +40,20 @@ void InventoryHandler::registerOpcodes(DispatchTable& table) {
table[Opcode::SMSG_LOOT_ROLL_WON] = [this](network::Packet& packet) { handleLootRollWon(packet); };
table[Opcode::SMSG_LOOT_MASTER_LIST] = [this](network::Packet& packet) {
masterLootCandidates_.clear();
if (packet.getSize() - packet.getReadPos() < 1) return;
if (!packet.hasRemaining(1)) return;
uint8_t mlCount = packet.readUInt8();
masterLootCandidates_.reserve(mlCount);
for (uint8_t i = 0; i < mlCount; ++i) {
if (packet.getSize() - packet.getReadPos() < 8) break;
if (!packet.hasRemaining(8)) break;
masterLootCandidates_.push_back(packet.readUInt64());
}
};
// ---- Loot money / misc consume ----
table[Opcode::SMSG_LOOT_MONEY_NOTIFY] = [this](network::Packet& packet) {
if (packet.getSize() - packet.getReadPos() < 4) return;
if (!packet.hasRemaining(4)) return;
uint32_t amount = packet.readUInt32();
if (packet.getSize() - packet.getReadPos() >= 1)
if (packet.hasRemaining(1))
/*uint8_t soleLooter =*/ packet.readUInt8();
owner_.playerMoneyCopper_ += amount;
owner_.pendingMoneyDelta_ = amount;
@ -103,7 +103,7 @@ void InventoryHandler::registerOpcodes(DispatchTable& table) {
// randProp(4) + countdown(4) + voteMask(1)
const bool hasMapId = isActiveExpansion("wotlk");
const size_t minSz = hasMapId ? 33 : 29;
if (packet.getSize() - packet.getReadPos() < minSz) return;
if (packet.getRemainingSize() < minSz) return;
uint64_t objectGuid = packet.readUInt64();
if (hasMapId) packet.readUInt32(); // mapId
uint32_t lootSlot = packet.readUInt32();
@ -137,7 +137,7 @@ void InventoryHandler::registerOpcodes(DispatchTable& table) {
table[Opcode::SMSG_LOOT_ALL_PASSED] = [this](network::Packet& packet) {
// objectGuid(8) + lootSlot(4) + itemId(4) + randSuffix(4) + randProp(4)
if (packet.getSize() - packet.getReadPos() < 24) return;
if (!packet.hasRemaining(24)) return;
/*uint64_t objectGuid =*/ packet.readUInt64();
/*uint32_t lootSlot =*/ packet.readUInt32();
uint32_t itemId = packet.readUInt32();
@ -154,13 +154,13 @@ void InventoryHandler::registerOpcodes(DispatchTable& table) {
table[Opcode::SMSG_LOOT_ITEM_NOTIFY] = [this](network::Packet& packet) {
// objectGuid(8) + lootSlot(1) [Classic: uint32; WotLK: uint8]
if (packet.getSize() - packet.getReadPos() < 9) return;
if (!packet.hasRemaining(9)) return;
/*uint64_t objectGuid =*/ packet.readUInt64();
uint32_t lootSlot;
if (isActiveExpansion("wotlk")) {
lootSlot = packet.readUInt8();
} else {
if (packet.getSize() - packet.getReadPos() < 4) return;
if (!packet.hasRemaining(4)) return;
lootSlot = packet.readUInt32();
}
// Try to resolve item name
@ -182,7 +182,7 @@ void InventoryHandler::registerOpcodes(DispatchTable& table) {
};
table[Opcode::SMSG_LOOT_SLOT_CHANGED] = [this](network::Packet& packet) {
if (packet.getSize() - packet.getReadPos() >= 1) {
if (packet.hasRemaining(1)) {
uint8_t slotIdx = packet.readUInt8();
LOG_DEBUG("SMSG_LOOT_SLOT_CHANGED: slot=", (int)slotIdx);
// The server re-sends loot info for this slot; we can refresh from
@ -194,7 +194,7 @@ void InventoryHandler::registerOpcodes(DispatchTable& table) {
table[Opcode::SMSG_ITEM_PUSH_RESULT] = [this](network::Packet& packet) {
// WotLK 3.3.5a: guid(8)+received(4)+created(4)+displayInChat(4)+bagSlot(1)
// +slot(4)+itemId(4)+suffixFactor(4)+randomPropertyId(4)+count(4)+countInInventory(4)
if (packet.getSize() - packet.getReadPos() < 45) return;
if (!packet.hasRemaining(45)) return;
uint64_t guid = packet.readUInt64();
if (guid != owner_.playerGuid) { packet.setReadPos(packet.getSize()); return; }
/*uint32_t received =*/ packet.readUInt32();
@ -238,7 +238,7 @@ void InventoryHandler::registerOpcodes(DispatchTable& table) {
// ---- Open container ----
table[Opcode::SMSG_OPEN_CONTAINER] = [this](network::Packet& packet) {
if (packet.getSize() - packet.getReadPos() >= 8) {
if (packet.hasRemaining(8)) {
uint64_t containerGuid = packet.readUInt64();
LOG_DEBUG("SMSG_OPEN_CONTAINER: guid=0x", std::hex, containerGuid, std::dec);
}
@ -246,7 +246,7 @@ void InventoryHandler::registerOpcodes(DispatchTable& table) {
// ---- Sell / Buy / Inventory ----
table[Opcode::SMSG_SELL_ITEM] = [this](network::Packet& packet) {
if ((packet.getSize() - packet.getReadPos()) >= 17) {
if ((packet.getRemainingSize()) >= 17) {
uint64_t vendorGuid = packet.readUInt64();
uint64_t itemGuid = packet.readUInt64();
uint8_t result = packet.readUInt8();
@ -307,16 +307,16 @@ void InventoryHandler::registerOpcodes(DispatchTable& table) {
};
table[Opcode::SMSG_INVENTORY_CHANGE_FAILURE] = [this](network::Packet& packet) {
if ((packet.getSize() - packet.getReadPos()) >= 1) {
if ((packet.getRemainingSize()) >= 1) {
uint8_t error = packet.readUInt8();
if (error != 0) {
LOG_WARNING("SMSG_INVENTORY_CHANGE_FAILURE: error=", (int)error);
uint32_t requiredLevel = 0;
if (packet.getSize() - packet.getReadPos() >= 17) {
if (packet.hasRemaining(17)) {
packet.readUInt64();
packet.readUInt64();
packet.readUInt8();
if (error == 1 && packet.getSize() - packet.getReadPos() >= 4)
if (error == 1 && packet.hasRemaining(4))
requiredLevel = packet.readUInt32();
}
const char* errMsg = nullptr;
@ -403,7 +403,7 @@ void InventoryHandler::registerOpcodes(DispatchTable& table) {
};
table[Opcode::SMSG_BUY_FAILED] = [this](network::Packet& packet) {
if (packet.getSize() - packet.getReadPos() >= 13) {
if (packet.hasRemaining(13)) {
uint64_t vendorGuid = packet.readUInt64();
uint32_t itemIdOrSlot = packet.readUInt32();
uint8_t errCode = packet.readUInt8();
@ -460,7 +460,7 @@ void InventoryHandler::registerOpcodes(DispatchTable& table) {
};
table[Opcode::SMSG_BUY_ITEM] = [this](network::Packet& packet) {
if (packet.getSize() - packet.getReadPos() >= 20) {
if (packet.hasRemaining(20)) {
/*uint64_t vendorGuid =*/ packet.readUInt64();
/*uint32_t vendorSlot =*/ packet.readUInt32();
/*int32_t newCount =*/ static_cast<int32_t>(packet.readUInt32());
@ -516,13 +516,13 @@ void InventoryHandler::registerOpcodes(DispatchTable& table) {
table[Opcode::SMSG_AUCTION_COMMAND_RESULT] = [this](network::Packet& packet) { handleAuctionCommandResult(packet); };
table[Opcode::SMSG_AUCTION_OWNER_NOTIFICATION] = [this](network::Packet& packet) {
if (packet.getSize() - packet.getReadPos() >= 16) {
if (packet.hasRemaining(16)) {
/*uint32_t auctionId =*/ packet.readUInt32();
uint32_t action = packet.readUInt32();
/*uint32_t error =*/ packet.readUInt32();
uint32_t itemEntry = packet.readUInt32();
int32_t ownerRandProp = 0;
if (packet.getSize() - packet.getReadPos() >= 4)
if (packet.hasRemaining(4))
ownerRandProp = static_cast<int32_t>(packet.readUInt32());
owner_.ensureItemInfo(itemEntry);
auto* info = owner_.getItemInfo(itemEntry);
@ -569,7 +569,7 @@ void InventoryHandler::registerOpcodes(DispatchTable& table) {
};
table[Opcode::SMSG_AUCTION_REMOVED_NOTIFICATION] = [this](network::Packet& packet) {
if (packet.getSize() - packet.getReadPos() >= 12) {
if (packet.hasRemaining(12)) {
/*uint32_t auctionId =*/ packet.readUInt32();
uint32_t itemEntry = packet.readUInt32();
int32_t itemRandom = static_cast<int32_t>(packet.readUInt32());
@ -591,7 +591,7 @@ void InventoryHandler::registerOpcodes(DispatchTable& table) {
table[Opcode::SMSG_EQUIPMENT_SET_LIST] = [this](network::Packet& packet) { handleEquipmentSetList(packet); };
table[Opcode::SMSG_EQUIPMENT_SET_SAVED] = [this](network::Packet& packet) {
std::string setName;
if (packet.getSize() - packet.getReadPos() >= 12) {
if (packet.hasRemaining(12)) {
uint32_t setIndex = packet.readUInt32();
uint64_t setGuid = packet.readUInt64();
bool found = false;
@ -637,7 +637,7 @@ void InventoryHandler::registerOpcodes(DispatchTable& table) {
};
table[Opcode::SMSG_EQUIPMENT_SET_USE_RESULT] = [this](network::Packet& packet) {
if (packet.getSize() - packet.getReadPos() >= 1) {
if (packet.hasRemaining(1)) {
uint8_t result = packet.readUInt8();
if (result != 0) { owner_.addUIError("Failed to equip item set."); owner_.addSystemChatMessage("Failed to equip item set."); }
}
@ -796,7 +796,7 @@ void InventoryHandler::sendLootRoll(uint64_t objectGuid, uint32_t slot, uint8_t
void InventoryHandler::handleLootRoll(network::Packet& packet) {
// objectGuid(8) + lootSlot(4) + playerGuid(8) + itemId(4) + itemRandSuffix(4) +
// itemRandProp(4) + rollNumber(1) + rollType(1) + autoPass(1)
if (packet.getSize() - packet.getReadPos() < 35) return;
if (!packet.hasRemaining(35)) return;
uint64_t objectGuid = packet.readUInt64();
uint32_t lootSlot = packet.readUInt32();
uint64_t playerGuid = packet.readUInt64();
@ -836,7 +836,7 @@ void InventoryHandler::handleLootRoll(network::Packet& packet) {
void InventoryHandler::handleLootRollWon(network::Packet& packet) {
// objectGuid(8) + lootSlot(4) + itemId(4) + itemSuffix(4) + itemProp(4) + playerGuid(8) + rollNumber(1) + rollType(1)
if (packet.getSize() - packet.getReadPos() < 34) return;
if (!packet.hasRemaining(34)) return;
/*uint64_t objectGuid =*/ packet.readUInt64();
/*uint32_t lootSlot =*/ packet.readUInt32();
uint32_t itemId = packet.readUInt32();
@ -1610,7 +1610,7 @@ void InventoryHandler::mailMarkAsRead(uint32_t mailId) {
}
void InventoryHandler::handleShowMailbox(network::Packet& packet) {
if (packet.getSize() - packet.getReadPos() < 8) return;
if (!packet.hasRemaining(8)) return;
mailboxGuid_ = packet.readUInt64();
mailboxOpen_ = true;
selectedMailIndex_ = -1;
@ -1629,7 +1629,7 @@ void InventoryHandler::handleMailListResult(network::Packet& packet) {
}
void InventoryHandler::handleSendMailResult(network::Packet& packet) {
if (packet.getSize() - packet.getReadPos() < 12) return;
if (!packet.hasRemaining(12)) return;
uint32_t mailId = packet.readUInt32();
uint32_t action = packet.readUInt32();
uint32_t error = packet.readUInt32();
@ -1735,13 +1735,13 @@ void InventoryHandler::withdrawItem(uint8_t srcBag, uint8_t srcSlot) {
}
void InventoryHandler::handleShowBank(network::Packet& packet) {
if (packet.getSize() - packet.getReadPos() < 8) return;
if (!packet.hasRemaining(8)) return;
uint64_t guid = packet.readUInt64();
openBank(guid);
}
void InventoryHandler::handleBuyBankSlotResult(network::Packet& packet) {
if (packet.getSize() - packet.getReadPos() < 4) return;
if (!packet.hasRemaining(4)) return;
uint32_t result = packet.readUInt32();
if (result == 0) {
owner_.addSystemChatMessage("Bank slot purchased.");
@ -1887,7 +1887,7 @@ void InventoryHandler::auctionListBidderItems(uint32_t offset) {
}
void InventoryHandler::handleAuctionHello(network::Packet& packet) {
if (packet.getSize() - packet.getReadPos() < 12) return;
if (!packet.hasRemaining(12)) return;
uint64_t guid = packet.readUInt64();
uint32_t houseId = packet.readUInt32();
auctioneerGuid_ = guid;
@ -1935,7 +1935,7 @@ void InventoryHandler::handleAuctionBidderListResult(network::Packet& packet) {
}
void InventoryHandler::handleAuctionCommandResult(network::Packet& packet) {
if (packet.getSize() - packet.getReadPos() < 12) return;
if (!packet.hasRemaining(12)) return;
uint32_t auctionId = packet.readUInt32();
uint32_t action = packet.readUInt32();
uint32_t error = packet.readUInt32();
@ -1986,7 +1986,7 @@ void InventoryHandler::queryItemText(uint64_t itemGuid) {
}
void InventoryHandler::handleItemTextQueryResponse(network::Packet& packet) {
if (packet.getSize() - packet.getReadPos() < 1) return;
if (!packet.hasRemaining(1)) return;
std::string text = packet.readString();
if (!text.empty()) {
itemText_ = std::move(text);
@ -2061,7 +2061,7 @@ void InventoryHandler::resetTradeState() {
}
void InventoryHandler::handleTradeStatus(network::Packet& packet) {
if (packet.getSize() - packet.getReadPos() < 4) return;
if (!packet.hasRemaining(4)) return;
uint32_t status = packet.readUInt32();
LOG_WARNING("SMSG_TRADE_STATUS: status=", status, " size=", packet.getSize());
switch (status) {
@ -2070,7 +2070,7 @@ void InventoryHandler::handleTradeStatus(network::Packet& packet) {
owner_.addSystemChatMessage("Trade failed: player is busy.");
break;
case 1: { // TRADE_STATUS_PROPOSED
if (packet.getSize() - packet.getReadPos() >= 8)
if (packet.hasRemaining(8))
tradePeerGuid_ = packet.readUInt64();
tradeStatus_ = TradeStatus::PendingIncoming;
// Resolve name
@ -2140,7 +2140,7 @@ void InventoryHandler::handleTradeStatusExtended(network::Packet& packet) {
" readPos=", packet.getReadPos());
// WotLK format: whichPlayer(4) + tradeCount(4) + N items × (slot(1)+64bytes) + gold(4)
// Total for empty trade: 8 + 8×65 + 4 = 532 (matches observed packet size)
if (packet.getSize() - packet.getReadPos() < 8) return;
if (!packet.hasRemaining(8)) return;
uint32_t whichPlayer = packet.readUInt32(); // 0=self, 1=peer (uint32 not uint8!)
uint32_t tradeCount = packet.readUInt32();
auto& slots = (whichPlayer == 0) ? myTradeSlots_ : peerTradeSlots_;
@ -2148,12 +2148,12 @@ void InventoryHandler::handleTradeStatusExtended(network::Packet& packet) {
LOG_WARNING(" whichPlayer=", whichPlayer, " tradeCount=", tradeCount);
for (uint32_t i = 0; i < tradeCount; ++i) {
if (packet.getSize() - packet.getReadPos() < 1) break;
if (!packet.hasRemaining(1)) break;
uint8_t slotNum = packet.readUInt8();
// Per-slot: 4(item)+4(display)+4(stack)+4(wrapped)+8(creator)
// +4(enchant)+3×4(gems)+4(maxDur)+4(dur)+4(spellCharges)
// +4(suffixFactor)+4(randomPropId)+4(lockId) = 64 bytes
if (packet.getSize() - packet.getReadPos() < 64) { packet.setReadPos(packet.getSize()); return; }
if (!packet.hasRemaining(64)) { packet.setReadPos(packet.getSize()); return; }
uint32_t itemId = packet.readUInt32();
uint32_t displayId = packet.readUInt32();
uint32_t stackCnt = packet.readUInt32();
@ -2177,7 +2177,7 @@ void InventoryHandler::handleTradeStatusExtended(network::Packet& packet) {
}
// Gold
if (packet.getSize() - packet.getReadPos() >= 4) {
if (packet.hasRemaining(4)) {
uint32_t gold = packet.readUInt32();
if (whichPlayer == 0) myTradeGold_ = gold;
else peerTradeGold_ = gold;
@ -2287,7 +2287,7 @@ void InventoryHandler::deleteEquipmentSet(uint64_t setGuid) {
}
void InventoryHandler::handleEquipmentSetList(network::Packet& packet) {
if (packet.getSize() - packet.getReadPos() < 4) return;
if (!packet.hasRemaining(4)) return;
uint32_t count = packet.readUInt32();
if (count > 10) {
LOG_WARNING("SMSG_EQUIPMENT_SET_LIST: unexpected count ", count, ", ignoring");
@ -2297,7 +2297,7 @@ void InventoryHandler::handleEquipmentSetList(network::Packet& packet) {
equipmentSets_.clear();
equipmentSets_.reserve(count);
for (uint32_t i = 0; i < count; ++i) {
if (packet.getSize() - packet.getReadPos() < 16) break;
if (!packet.hasRemaining(16)) break;
EquipmentSet es;
es.setGuid = packet.readUInt64();
es.setId = packet.readUInt32();
@ -2305,7 +2305,7 @@ void InventoryHandler::handleEquipmentSetList(network::Packet& packet) {
es.iconName = packet.readString();
es.ignoreSlotMask = packet.readUInt32();
for (int slot = 0; slot < 19; ++slot) {
if (packet.getSize() - packet.getReadPos() < 8) break;
if (!packet.hasRemaining(8)) break;
es.itemGuids[slot] = packet.readUInt64();
}
equipmentSets_.push_back(std::move(es));

View file

@ -40,7 +40,7 @@ void MovementHandler::registerOpcodes(DispatchTable& table) {
Opcode::SMSG_SPLINE_MOVE_ROOT,
Opcode::SMSG_SPLINE_MOVE_SET_HOVER }) {
table[op] = [this](network::Packet& packet) {
if (packet.getSize() - packet.getReadPos() >= 1)
if (packet.hasRemaining(1))
(void)packet.readPackedGuid();
};
}
@ -49,7 +49,7 @@ void MovementHandler::registerOpcodes(DispatchTable& table) {
{
auto makeSynthHandler = [this](uint32_t synthFlags) {
return [this, synthFlags](network::Packet& packet) {
if (packet.getSize() - packet.getReadPos() < 1) return;
if (!packet.hasRemaining(1)) return;
uint64_t guid = packet.readPackedGuid();
if (guid == 0 || guid == owner_.playerGuid || !owner_.unitMoveFlagsCallback_) return;
owner_.unitMoveFlagsCallback_(guid, synthFlags);
@ -809,7 +809,7 @@ void MovementHandler::handleForceSpeedChange(network::Packet& packet, const char
? packet.readUInt64() : packet.readPackedGuid();
uint32_t counter = packet.readUInt32();
size_t remaining = packet.getSize() - packet.getReadPos();
size_t remaining = packet.getRemainingSize();
if (remaining >= 8) {
packet.readUInt32();
} else if (remaining >= 5) {
@ -853,10 +853,10 @@ void MovementHandler::handleForceRunSpeedChange(network::Packet& packet) {
void MovementHandler::handleForceMoveRootState(network::Packet& packet, bool rooted) {
const bool rootTbc = isClassicLikeExpansion() || isActiveExpansion("tbc");
if (packet.getSize() - packet.getReadPos() < (rootTbc ? 8u : 2u)) return;
if (packet.getRemainingSize() < (rootTbc ? 8u : 2u)) return;
uint64_t guid = rootTbc
? packet.readUInt64() : packet.readPackedGuid();
if (packet.getSize() - packet.getReadPos() < 4) return;
if (!packet.hasRemaining(4)) return;
uint32_t counter = packet.readUInt32();
LOG_INFO(rooted ? "SMSG_FORCE_MOVE_ROOT" : "SMSG_FORCE_MOVE_UNROOT",
@ -879,10 +879,10 @@ void MovementHandler::handleForceMoveRootState(network::Packet& packet, bool roo
void MovementHandler::handleForceMoveFlagChange(network::Packet& packet, const char* name,
Opcode ackOpcode, uint32_t flag, bool set) {
const bool fmfTbcLike = isClassicLikeExpansion() || isActiveExpansion("tbc");
if (packet.getSize() - packet.getReadPos() < (fmfTbcLike ? 8u : 2u)) return;
if (packet.getRemainingSize() < (fmfTbcLike ? 8u : 2u)) return;
uint64_t guid = fmfTbcLike
? packet.readUInt64() : packet.readPackedGuid();
if (packet.getSize() - packet.getReadPos() < 4) return;
if (!packet.hasRemaining(4)) return;
uint32_t counter = packet.readUInt32();
LOG_INFO("SMSG_FORCE_", name, ": guid=0x", std::hex, guid, std::dec, " counter=", counter);
@ -904,9 +904,9 @@ void MovementHandler::handleForceMoveFlagChange(network::Packet& packet, const c
void MovementHandler::handleMoveSetCollisionHeight(network::Packet& packet) {
const bool legacyGuid = isClassicLikeExpansion() || isActiveExpansion("tbc");
if (packet.getSize() - packet.getReadPos() < (legacyGuid ? 8u : 2u)) return;
if (packet.getRemainingSize() < (legacyGuid ? 8u : 2u)) return;
uint64_t guid = legacyGuid ? packet.readUInt64() : packet.readPackedGuid();
if (packet.getSize() - packet.getReadPos() < 8) return;
if (!packet.hasRemaining(8)) return;
uint32_t counter = packet.readUInt32();
float height = packet.readFloat();
@ -926,10 +926,10 @@ void MovementHandler::handleMoveSetCollisionHeight(network::Packet& packet) {
void MovementHandler::handleMoveKnockBack(network::Packet& packet) {
const bool mkbTbc = isClassicLikeExpansion() || isActiveExpansion("tbc");
if (packet.getSize() - packet.getReadPos() < (mkbTbc ? 8u : 2u)) return;
if (packet.getRemainingSize() < (mkbTbc ? 8u : 2u)) return;
uint64_t guid = mkbTbc
? packet.readUInt64() : packet.readPackedGuid();
if (packet.getSize() - packet.getReadPos() < 20) return;
if (!packet.hasRemaining(20)) return;
uint32_t counter = packet.readUInt32();
float vcos = packet.readFloat();
float vsin = packet.readFloat();
@ -960,7 +960,7 @@ void MovementHandler::handleMoveSetSpeed(network::Packet& packet) {
uint64_t moverGuid = useFull
? packet.readUInt64() : packet.readPackedGuid();
const size_t remaining = packet.getSize() - packet.getReadPos();
const size_t remaining = packet.getRemainingSize();
if (remaining < 4) return;
if (remaining > 4) {
packet.setReadPos(packet.getSize() - 4);
@ -1466,7 +1466,7 @@ void MovementHandler::handleMonsterMove(network::Packet& packet) {
}
void MovementHandler::handleMonsterMoveTransport(network::Packet& packet) {
if (packet.getSize() - packet.getReadPos() < 8 + 1 + 8 + 12) return;
if (packet.getRemainingSize() < 8 + 1 + 8 + 12) return;
uint64_t moverGuid = packet.readUInt64();
/*uint8_t unk =*/ packet.readUInt8();
uint64_t transportGuid = packet.readUInt64();
@ -1618,19 +1618,19 @@ void MovementHandler::handleMonsterMoveTransport(network::Packet& packet) {
void MovementHandler::handleTeleportAck(network::Packet& packet) {
const bool taTbc = isClassicLikeExpansion() || isActiveExpansion("tbc");
if (packet.getSize() - packet.getReadPos() < (taTbc ? 8u : 4u)) {
if (packet.getRemainingSize() < (taTbc ? 8u : 4u)) {
LOG_WARNING("MSG_MOVE_TELEPORT_ACK too short");
return;
}
uint64_t guid = taTbc
? packet.readUInt64() : packet.readPackedGuid();
if (packet.getSize() - packet.getReadPos() < 4) return;
if (!packet.hasRemaining(4)) return;
uint32_t counter = packet.readUInt32();
const bool taNoFlags2 = isClassicLikeExpansion() || isActiveExpansion("tbc");
const size_t minMoveSz = taNoFlags2 ? (4 + 4 + 4 * 4) : (4 + 2 + 4 + 4 * 4);
if (packet.getSize() - packet.getReadPos() < minMoveSz) {
if (packet.getRemainingSize() < minMoveSz) {
LOG_WARNING("MSG_MOVE_TELEPORT_ACK: not enough data for movement info");
return;
}
@ -1679,7 +1679,7 @@ void MovementHandler::handleTeleportAck(network::Packet& packet) {
}
void MovementHandler::handleNewWorld(network::Packet& packet) {
if (packet.getSize() - packet.getReadPos() < 20) {
if (!packet.hasRemaining(20)) {
LOG_WARNING("SMSG_NEW_WORLD too short");
return;
}

View file

@ -299,7 +299,7 @@ void QuestHandler::registerOpcodes(DispatchTable& table) {
// ---- SMSG_GOSSIP_POI ----
table[Opcode::SMSG_GOSSIP_POI] = [this](network::Packet& packet) {
if (packet.getSize() - packet.getReadPos() < 20) return;
if (!packet.hasRemaining(20)) return;
/*uint32_t flags =*/ packet.readUInt32();
float poiX = packet.readFloat();
float poiY = packet.readFloat();
@ -335,7 +335,7 @@ void QuestHandler::registerOpcodes(DispatchTable& table) {
// ---- SMSG_QUESTGIVER_STATUS ----
table[Opcode::SMSG_QUESTGIVER_STATUS] = [this](network::Packet& packet) {
if (packet.getSize() - packet.getReadPos() >= 9) {
if (packet.hasRemaining(9)) {
uint64_t npcGuid = packet.readUInt64();
uint8_t status = owner_.packetParsers_->readQuestGiverStatus(packet);
npcQuestStatus_[npcGuid] = static_cast<QuestGiverStatus>(status);
@ -344,10 +344,10 @@ void QuestHandler::registerOpcodes(DispatchTable& table) {
// ---- SMSG_QUESTGIVER_STATUS_MULTIPLE ----
table[Opcode::SMSG_QUESTGIVER_STATUS_MULTIPLE] = [this](network::Packet& packet) {
if (packet.getSize() - packet.getReadPos() < 4) return;
if (!packet.hasRemaining(4)) return;
uint32_t count = packet.readUInt32();
for (uint32_t i = 0; i < count; ++i) {
if (packet.getSize() - packet.getReadPos() < 9) break;
if (!packet.hasRemaining(9)) break;
uint64_t npcGuid = packet.readUInt64();
uint8_t status = owner_.packetParsers_->readQuestGiverStatus(packet);
npcQuestStatus_[npcGuid] = static_cast<QuestGiverStatus>(status);
@ -356,7 +356,7 @@ void QuestHandler::registerOpcodes(DispatchTable& table) {
// ---- SMSG_QUESTUPDATE_FAILED ----
table[Opcode::SMSG_QUESTUPDATE_FAILED] = [this](network::Packet& packet) {
if (packet.getSize() - packet.getReadPos() >= 4) {
if (packet.hasRemaining(4)) {
uint32_t questId = packet.readUInt32();
std::string questTitle;
for (const auto& q : questLog_)
@ -368,7 +368,7 @@ void QuestHandler::registerOpcodes(DispatchTable& table) {
// ---- SMSG_QUESTUPDATE_FAILEDTIMER ----
table[Opcode::SMSG_QUESTUPDATE_FAILEDTIMER] = [this](network::Packet& packet) {
if (packet.getSize() - packet.getReadPos() >= 4) {
if (packet.hasRemaining(4)) {
uint32_t questId = packet.readUInt32();
std::string questTitle;
for (const auto& q : questLog_)
@ -381,7 +381,7 @@ void QuestHandler::registerOpcodes(DispatchTable& table) {
// ---- SMSG_QUESTGIVER_QUEST_FAILED ----
table[Opcode::SMSG_QUESTGIVER_QUEST_FAILED] = [this](network::Packet& packet) {
// uint32 questId + uint32 reason
if (packet.getSize() - packet.getReadPos() >= 8) {
if (packet.hasRemaining(8)) {
uint32_t questId = packet.readUInt32();
uint32_t reason = packet.readUInt32();
std::string questTitle;
@ -407,7 +407,7 @@ void QuestHandler::registerOpcodes(DispatchTable& table) {
// ---- SMSG_QUESTGIVER_QUEST_INVALID ----
table[Opcode::SMSG_QUESTGIVER_QUEST_INVALID] = [this](network::Packet& packet) {
if (packet.getSize() - packet.getReadPos() >= 4) {
if (packet.hasRemaining(4)) {
uint32_t failReason = packet.readUInt32();
pendingTurnInRewardRequest_ = false;
const char* reasonStr = "Unknown";
@ -454,7 +454,7 @@ void QuestHandler::registerOpcodes(DispatchTable& table) {
// ---- SMSG_QUESTGIVER_QUEST_COMPLETE ----
table[Opcode::SMSG_QUESTGIVER_QUEST_COMPLETE] = [this](network::Packet& packet) {
if (packet.getSize() - packet.getReadPos() >= 4) {
if (packet.hasRemaining(4)) {
uint32_t questId = packet.readUInt32();
LOG_INFO("Quest completed: questId=", questId);
if (pendingTurnInQuestId_ == questId) {
@ -501,14 +501,14 @@ void QuestHandler::registerOpcodes(DispatchTable& table) {
// ---- SMSG_QUESTUPDATE_ADD_KILL ----
table[Opcode::SMSG_QUESTUPDATE_ADD_KILL] = [this](network::Packet& packet) {
size_t rem = packet.getSize() - packet.getReadPos();
size_t rem = packet.getRemainingSize();
if (rem >= 12) {
uint32_t questId = packet.readUInt32();
clearPendingQuestAccept(questId);
uint32_t entry = packet.readUInt32();
uint32_t count = packet.readUInt32();
uint32_t reqCount = 0;
if (packet.getSize() - packet.getReadPos() >= 4) {
if (packet.hasRemaining(4)) {
reqCount = packet.readUInt32();
}
@ -575,7 +575,7 @@ void QuestHandler::registerOpcodes(DispatchTable& table) {
// ---- SMSG_QUESTUPDATE_ADD_ITEM ----
table[Opcode::SMSG_QUESTUPDATE_ADD_ITEM] = [this](network::Packet& packet) {
if (packet.getSize() - packet.getReadPos() >= 8) {
if (packet.hasRemaining(8)) {
uint32_t itemId = packet.readUInt32();
uint32_t count = packet.readUInt32();
owner_.queryItemInfo(itemId, 0);
@ -640,14 +640,14 @@ void QuestHandler::registerOpcodes(DispatchTable& table) {
// ---- SMSG_QUESTUPDATE_COMPLETE ----
table[Opcode::SMSG_QUESTUPDATE_COMPLETE] = [this](network::Packet& packet) {
size_t rem = packet.getSize() - packet.getReadPos();
size_t rem = packet.getRemainingSize();
if (rem >= 12) {
uint32_t questId = packet.readUInt32();
clearPendingQuestAccept(questId);
uint32_t entry = packet.readUInt32();
uint32_t count = packet.readUInt32();
uint32_t reqCount = 0;
if (packet.getSize() - packet.getReadPos() >= 4) reqCount = packet.readUInt32();
if (packet.hasRemaining(4)) reqCount = packet.readUInt32();
if (reqCount == 0) reqCount = count;
LOG_INFO("Quest kill update (compat via COMPLETE): questId=", questId,
" entry=", entry, " count=", count, "/", reqCount);
@ -677,7 +677,7 @@ void QuestHandler::registerOpcodes(DispatchTable& table) {
// ---- SMSG_QUEST_FORCE_REMOVE ----
table[Opcode::SMSG_QUEST_FORCE_REMOVE] = [this](network::Packet& packet) {
if (packet.getSize() - packet.getReadPos() < 4) {
if (!packet.hasRemaining(4)) {
LOG_WARNING("SMSG_QUEST_FORCE_REMOVE/SET_REST_START too short");
return;
}
@ -832,12 +832,12 @@ void QuestHandler::registerOpcodes(DispatchTable& table) {
// ---- SMSG_QUESTUPDATE_ADD_PVP_KILL ----
table[Opcode::SMSG_QUESTUPDATE_ADD_PVP_KILL] = [this](network::Packet& packet) {
if (packet.getSize() - packet.getReadPos() >= 16) {
if (packet.hasRemaining(16)) {
/*uint64_t guid =*/ packet.readUInt64();
uint32_t questId = packet.readUInt32();
uint32_t count = packet.readUInt32();
uint32_t reqCount = 0;
if (packet.getSize() - packet.getReadPos() >= 4) {
if (packet.hasRemaining(4)) {
reqCount = packet.readUInt32();
}
@ -1515,7 +1515,7 @@ void QuestHandler::handleGossipMessage(network::Packet& packet) {
}
void QuestHandler::handleQuestgiverQuestList(network::Packet& packet) {
if (packet.getSize() - packet.getReadPos() < 8) return;
if (!packet.hasRemaining(8)) return;
GossipMessageData data;
data.npcGuid = packet.readUInt64();
@ -1523,7 +1523,7 @@ void QuestHandler::handleQuestgiverQuestList(network::Packet& packet) {
data.titleTextId = 0;
std::string header = packet.readString();
if (packet.getSize() - packet.getReadPos() >= 8) {
if (packet.hasRemaining(8)) {
(void)packet.readUInt32(); // emoteDelay / unk
(void)packet.readUInt32(); // emote / unk
}
@ -1531,7 +1531,7 @@ void QuestHandler::handleQuestgiverQuestList(network::Packet& packet) {
// questCount is uint8 in all WoW versions for SMSG_QUESTGIVER_QUEST_LIST.
uint32_t questCount = 0;
if (packet.getSize() - packet.getReadPos() >= 1) {
if (packet.hasRemaining(1)) {
questCount = packet.readUInt8();
}
@ -1539,13 +1539,13 @@ void QuestHandler::handleQuestgiverQuestList(network::Packet& packet) {
data.quests.reserve(questCount);
for (uint32_t i = 0; i < questCount; ++i) {
if (packet.getSize() - packet.getReadPos() < 12) break;
if (!packet.hasRemaining(12)) break;
GossipQuestItem q;
q.questId = packet.readUInt32();
q.questIcon = packet.readUInt32();
q.questLevel = static_cast<int32_t>(packet.readUInt32());
if (hasQuestFlagsField && packet.getSize() - packet.getReadPos() >= 5) {
if (hasQuestFlagsField && packet.hasRemaining(5)) {
q.questFlags = packet.readUInt32();
q.isRepeatable = packet.readUInt8();
} else {
@ -1643,10 +1643,10 @@ void QuestHandler::handleQuestPoiQueryResponse(network::Packet& packet) {
// uint32 unk2
// uint32 pointCount
// per point: int32 x, int32 y
if (packet.getSize() - packet.getReadPos() < 4) return;
if (!packet.hasRemaining(4)) return;
const uint32_t questCount = packet.readUInt32();
for (uint32_t qi = 0; qi < questCount; ++qi) {
if (packet.getSize() - packet.getReadPos() < 8) return;
if (!packet.hasRemaining(8)) return;
const uint32_t questId = packet.readUInt32();
const uint32_t poiCount = packet.readUInt32();
@ -1665,7 +1665,7 @@ void QuestHandler::handleQuestPoiQueryResponse(network::Packet& packet) {
}
for (uint32_t pi = 0; pi < poiCount; ++pi) {
if (packet.getSize() - packet.getReadPos() < 28) return;
if (!packet.hasRemaining(28)) return;
packet.readUInt32(); // poiId
packet.readUInt32(); // objIndex (int32)
const uint32_t mapId = packet.readUInt32();
@ -1675,7 +1675,7 @@ void QuestHandler::handleQuestPoiQueryResponse(network::Packet& packet) {
packet.readUInt32(); // unk2
const uint32_t pointCount = packet.readUInt32();
if (pointCount == 0) continue;
if (packet.getSize() - packet.getReadPos() < pointCount * 8) return;
if (packet.getRemainingSize() < pointCount * 8) return;
float sumX = 0.0f, sumY = 0.0f;
for (uint32_t pt = 0; pt < pointCount; ++pt) {
const int32_t px = static_cast<int32_t>(packet.readUInt32());
@ -1816,12 +1816,12 @@ void QuestHandler::handleQuestOfferReward(network::Packet& packet) {
}
void QuestHandler::handleQuestConfirmAccept(network::Packet& packet) {
size_t rem = packet.getSize() - packet.getReadPos();
size_t rem = packet.getRemainingSize();
if (rem < 4) return;
sharedQuestId_ = packet.readUInt32();
sharedQuestTitle_ = packet.readString();
if (packet.getSize() - packet.getReadPos() >= 8) {
if (packet.hasRemaining(8)) {
sharedQuestSharerGuid_ = packet.readUInt64();
}

View file

@ -152,7 +152,7 @@ void SocialHandler::registerOpcodes(DispatchTable& table) {
readyCheckNotReadyCount_ = 0;
readyCheckInitiator_.clear();
readyCheckResults_.clear();
if (packet.getSize() - packet.getReadPos() >= 8) {
if (packet.hasRemaining(8)) {
uint64_t initiatorGuid = packet.readUInt64();
auto entity = owner_.getEntityManager().getEntity(initiatorGuid);
if (auto* unit = dynamic_cast<Unit*>(entity.get()))
@ -170,7 +170,7 @@ void SocialHandler::registerOpcodes(DispatchTable& table) {
owner_.addonEventCallback_("READY_CHECK", {readyCheckInitiator_});
};
table[Opcode::MSG_RAID_READY_CHECK_CONFIRM] = [this](network::Packet& packet) {
if (packet.getSize() - packet.getReadPos() < 9) { packet.setReadPos(packet.getSize()); return; }
if (!packet.hasRemaining(9)) { packet.setReadPos(packet.getSize()); return; }
uint64_t respGuid = packet.readUInt64();
uint8_t isReady = packet.readUInt8();
if (isReady) ++readyCheckReadyCount_; else ++readyCheckNotReadyCount_;
@ -223,14 +223,14 @@ void SocialHandler::registerOpcodes(DispatchTable& table) {
};
table[Opcode::SMSG_DUEL_INBOUNDS] = [this](network::Packet& /*packet*/) {};
table[Opcode::SMSG_DUEL_COUNTDOWN] = [this](network::Packet& packet) {
if (packet.getSize() - packet.getReadPos() >= 4) {
if (packet.hasRemaining(4)) {
uint32_t ms = packet.readUInt32();
duelCountdownMs_ = (ms > 0 && ms <= 30000) ? ms : 3000;
duelCountdownStartedAt_ = std::chrono::steady_clock::now();
}
};
table[Opcode::SMSG_PARTYKILLLOG] = [this](network::Packet& packet) {
if (packet.getSize() - packet.getReadPos() < 16) return;
if (!packet.hasRemaining(16)) return;
uint64_t killerGuid = packet.readUInt64();
uint64_t victimGuid = packet.readUInt64();
auto nameFor = [this](uint64_t g) -> std::string {
@ -261,7 +261,7 @@ void SocialHandler::registerOpcodes(DispatchTable& table) {
table[Opcode::SMSG_PETITION_SHOWLIST] = [this](network::Packet& packet) { handlePetitionShowlist(packet); };
table[Opcode::SMSG_TURN_IN_PETITION_RESULTS] = [this](network::Packet& packet) { handleTurnInPetitionResults(packet); };
table[Opcode::SMSG_OFFER_PETITION_ERROR] = [this](network::Packet& packet) {
if (packet.getSize() - packet.getReadPos() >= 4) {
if (packet.hasRemaining(4)) {
uint32_t err = packet.readUInt32();
if (err == 1) owner_.addSystemChatMessage("Player is already in a guild.");
else if (err == 2) owner_.addSystemChatMessage("Player already has a petition.");
@ -282,9 +282,9 @@ void SocialHandler::registerOpcodes(DispatchTable& table) {
table[Opcode::MSG_BATTLEGROUND_PLAYER_POSITIONS] = [this](network::Packet& packet) {
bgPlayerPositions_.clear();
for (int grp = 0; grp < 2; ++grp) {
if (packet.getSize() - packet.getReadPos() < 4) break;
if (!packet.hasRemaining(4)) break;
uint32_t count = packet.readUInt32();
for (uint32_t i = 0; i < count && packet.getSize() - packet.getReadPos() >= 16; ++i) {
for (uint32_t i = 0; i < count && packet.getRemainingSize() >= 16; ++i) {
BgPlayerPosition pos;
pos.guid = packet.readUInt64();
pos.wowX = packet.readFloat();
@ -304,7 +304,7 @@ void SocialHandler::registerOpcodes(DispatchTable& table) {
owner_.addSystemChatMessage("You have joined the battleground queue.");
};
table[Opcode::SMSG_BATTLEGROUND_PLAYER_JOINED] = [this](network::Packet& packet) {
if (packet.getSize() - packet.getReadPos() >= 8) {
if (packet.hasRemaining(8)) {
uint64_t guid = packet.readUInt64();
auto it = owner_.getPlayerNameCache().find(guid);
if (it != owner_.getPlayerNameCache().end() && !it->second.empty())
@ -312,7 +312,7 @@ void SocialHandler::registerOpcodes(DispatchTable& table) {
}
};
table[Opcode::SMSG_BATTLEGROUND_PLAYER_LEFT] = [this](network::Packet& packet) {
if (packet.getSize() - packet.getReadPos() >= 8) {
if (packet.hasRemaining(8)) {
uint64_t guid = packet.readUInt64();
auto it = owner_.getPlayerNameCache().find(guid);
if (it != owner_.getPlayerNameCache().end() && !it->second.empty())
@ -369,13 +369,13 @@ void SocialHandler::registerOpcodes(DispatchTable& table) {
owner_.addSystemChatMessage("You are now saved to this instance.");
};
table[Opcode::SMSG_RAID_INSTANCE_MESSAGE] = [this](network::Packet& packet) {
if (packet.getSize() - packet.getReadPos() < 12) return;
if (!packet.hasRemaining(12)) return;
uint32_t msgType = packet.readUInt32();
uint32_t mapId = packet.readUInt32();
packet.readUInt32(); // diff
std::string mapLabel = owner_.getMapName(mapId);
if (mapLabel.empty()) mapLabel = "instance #" + std::to_string(mapId);
if (msgType == 1 && packet.getSize() - packet.getReadPos() >= 4) {
if (msgType == 1 && packet.hasRemaining(4)) {
uint32_t timeLeft = packet.readUInt32();
owner_.addSystemChatMessage(mapLabel + " will reset in " + std::to_string(timeLeft / 60) + " minute(s).");
} else if (msgType == 2) {
@ -385,7 +385,7 @@ void SocialHandler::registerOpcodes(DispatchTable& table) {
}
};
table[Opcode::SMSG_INSTANCE_RESET] = [this](network::Packet& packet) {
if (packet.getSize() - packet.getReadPos() < 4) return;
if (!packet.hasRemaining(4)) return;
uint32_t mapId = packet.readUInt32();
auto it = std::remove_if(instanceLockouts_.begin(), instanceLockouts_.end(),
[mapId](const InstanceLockout& lo){ return lo.mapId == mapId; });
@ -395,7 +395,7 @@ void SocialHandler::registerOpcodes(DispatchTable& table) {
owner_.addSystemChatMessage(mapLabel + " has been reset.");
};
table[Opcode::SMSG_INSTANCE_RESET_FAILED] = [this](network::Packet& packet) {
if (packet.getSize() - packet.getReadPos() < 8) return;
if (!packet.hasRemaining(8)) return;
uint32_t mapId = packet.readUInt32();
uint32_t reason = packet.readUInt32();
static const char* resetFailReasons[] = {
@ -409,7 +409,7 @@ void SocialHandler::registerOpcodes(DispatchTable& table) {
owner_.addSystemChatMessage("Cannot reset " + mapLabel + ": " + reasonMsg);
};
table[Opcode::SMSG_INSTANCE_LOCK_WARNING_QUERY] = [this](network::Packet& packet) {
if (!owner_.socket || packet.getSize() - packet.getReadPos() < 17) return;
if (!owner_.socket || !packet.hasRemaining(17)) return;
uint32_t ilMapId = packet.readUInt32();
uint32_t ilDiff = packet.readUInt32();
uint32_t ilTimeLeft = packet.readUInt32();
@ -448,7 +448,7 @@ void SocialHandler::registerOpcodes(DispatchTable& table) {
owner_.addSystemChatMessage("Dungeon Finder: You may continue your dungeon.");
};
table[Opcode::SMSG_LFG_ROLE_CHOSEN] = [this](network::Packet& packet) {
if (packet.getSize() - packet.getReadPos() < 13) { packet.setReadPos(packet.getSize()); return; }
if (!packet.hasRemaining(13)) { packet.setReadPos(packet.getSize()); return; }
uint64_t roleGuid = packet.readUInt64();
uint8_t ready = packet.readUInt8();
uint32_t roles = packet.readUInt32();
@ -558,12 +558,12 @@ void SocialHandler::inspectTarget() {
}
void SocialHandler::handleInspectResults(network::Packet& packet) {
if (packet.getSize() - packet.getReadPos() < 1) return;
if (!packet.hasRemaining(1)) return;
uint8_t talentType = packet.readUInt8();
if (talentType == 0) {
// Own talent info
if (packet.getSize() - packet.getReadPos() < 6) {
if (!packet.hasRemaining(6)) {
LOG_DEBUG("SMSG_TALENTS_INFO type=0: too short");
return;
}
@ -573,20 +573,20 @@ void SocialHandler::handleInspectResults(network::Packet& packet) {
if (activeTalentGroup > 1) activeTalentGroup = 0;
owner_.activeTalentSpec_ = activeTalentGroup;
for (uint8_t g = 0; g < talentGroupCount && g < 2; ++g) {
if (packet.getSize() - packet.getReadPos() < 1) break;
if (!packet.hasRemaining(1)) break;
uint8_t talentCount = packet.readUInt8();
owner_.learnedTalents_[g].clear();
for (uint8_t t = 0; t < talentCount; ++t) {
if (packet.getSize() - packet.getReadPos() < 5) break;
if (!packet.hasRemaining(5)) break;
uint32_t talentId = packet.readUInt32();
uint8_t rank = packet.readUInt8();
owner_.learnedTalents_[g][talentId] = rank + 1u;
}
if (packet.getSize() - packet.getReadPos() < 1) break;
if (!packet.hasRemaining(1)) break;
owner_.learnedGlyphs_[g].fill(0);
uint8_t glyphCount = packet.readUInt8();
for (uint8_t gl = 0; gl < glyphCount; ++gl) {
if (packet.getSize() - packet.getReadPos() < 2) break;
if (!packet.hasRemaining(2)) break;
uint16_t glyphId = packet.readUInt16();
if (gl < GameHandler::MAX_GLYPH_SLOTS) owner_.learnedGlyphs_[g][gl] = glyphId;
}
@ -608,12 +608,12 @@ void SocialHandler::handleInspectResults(network::Packet& packet) {
// talentType == 1: inspect result
const bool talentTbc = isClassicLikeExpansion() || isActiveExpansion("tbc");
if (packet.getSize() - packet.getReadPos() < (talentTbc ? 8u : 2u)) return;
if (packet.getRemainingSize() < (talentTbc ? 8u : 2u)) return;
uint64_t guid = talentTbc
? packet.readUInt64() : packet.readPackedGuid();
if (guid == 0) return;
size_t bytesLeft = packet.getSize() - packet.getReadPos();
size_t bytesLeft = packet.getRemainingSize();
if (bytesLeft < 6) {
LOG_WARNING("SMSG_TALENTS_INFO: too short after guid, ", bytesLeft, " bytes");
auto entity = owner_.getEntityManager().getEntity(guid);
@ -639,33 +639,33 @@ void SocialHandler::handleInspectResults(network::Packet& packet) {
uint32_t totalTalents = 0;
for (uint8_t g = 0; g < talentGroupCount && g < 2; ++g) {
bytesLeft = packet.getSize() - packet.getReadPos();
bytesLeft = packet.getRemainingSize();
if (bytesLeft < 1) break;
uint8_t talentCount = packet.readUInt8();
for (uint8_t t = 0; t < talentCount; ++t) {
bytesLeft = packet.getSize() - packet.getReadPos();
bytesLeft = packet.getRemainingSize();
if (bytesLeft < 5) break;
packet.readUInt32();
packet.readUInt8();
totalTalents++;
}
bytesLeft = packet.getSize() - packet.getReadPos();
bytesLeft = packet.getRemainingSize();
if (bytesLeft < 1) break;
uint8_t glyphCount = packet.readUInt8();
for (uint8_t gl = 0; gl < glyphCount; ++gl) {
bytesLeft = packet.getSize() - packet.getReadPos();
bytesLeft = packet.getRemainingSize();
if (bytesLeft < 2) break;
packet.readUInt16();
}
}
std::array<uint16_t, 19> enchantIds{};
bytesLeft = packet.getSize() - packet.getReadPos();
bytesLeft = packet.getRemainingSize();
if (bytesLeft >= 4) {
uint32_t slotMask = packet.readUInt32();
for (int slot = 0; slot < 19; ++slot) {
if (slotMask & (1u << slot)) {
bytesLeft = packet.getSize() - packet.getReadPos();
bytesLeft = packet.getRemainingSize();
if (bytesLeft < 2) break;
enchantIds[slot] = packet.readUInt16();
}
@ -1031,7 +1031,7 @@ void SocialHandler::reportPlayer(uint64_t targetGuid, const std::string& reason)
}
void SocialHandler::handleDuelRequested(network::Packet& packet) {
if (packet.getSize() - packet.getReadPos() < 16) { packet.setReadPos(packet.getSize()); return; }
if (!packet.hasRemaining(16)) { packet.setReadPos(packet.getSize()); return; }
duelChallengerGuid_ = packet.readUInt64();
duelFlagGuid_ = packet.readUInt64();
duelChallengerName_.clear();
@ -1055,7 +1055,7 @@ void SocialHandler::handleDuelRequested(network::Packet& packet) {
}
void SocialHandler::handleDuelComplete(network::Packet& packet) {
if (packet.getSize() - packet.getReadPos() < 1) return;
if (!packet.hasRemaining(1)) return;
uint8_t started = packet.readUInt8();
pendingDuelRequest_ = false;
duelCountdownMs_ = 0;
@ -1064,7 +1064,7 @@ void SocialHandler::handleDuelComplete(network::Packet& packet) {
}
void SocialHandler::handleDuelWinner(network::Packet& packet) {
if (packet.getSize() - packet.getReadPos() < 3) return;
if (!packet.hasRemaining(3)) return;
uint8_t duelType = packet.readUInt8();
std::string winner = packet.readString();
std::string loser = packet.readString();
@ -1300,7 +1300,7 @@ void SocialHandler::handlePartyCommandResult(network::Packet& packet) {
}
void SocialHandler::handlePartyMemberStats(network::Packet& packet, bool isFull) {
auto remaining = [&]() { return packet.getSize() - packet.getReadPos(); };
auto remaining = [&]() { return packet.getRemainingSize(); };
const bool isWotLK = isActiveExpansion("wotlk");
if (isFull) { if (remaining() < 1) return; packet.readUInt8(); }
@ -1605,7 +1605,7 @@ void SocialHandler::handlePetitionShowlist(network::Packet& packet) {
}
void SocialHandler::handlePetitionQueryResponse(network::Packet& packet) {
auto rem = [&]() { return packet.getSize() - packet.getReadPos(); };
auto rem = [&]() { return packet.getRemainingSize(); };
if (rem() < 12) return;
/*uint32_t entry =*/ packet.readUInt32();
uint64_t petGuid = packet.readUInt64();
@ -1616,7 +1616,7 @@ void SocialHandler::handlePetitionQueryResponse(network::Packet& packet) {
}
void SocialHandler::handlePetitionShowSignatures(network::Packet& packet) {
auto rem = [&]() { return packet.getSize() - packet.getReadPos(); };
auto rem = [&]() { return packet.getRemainingSize(); };
if (rem() < 21) return;
petitionInfo_ = PetitionInfo{};
petitionInfo_.petitionGuid = packet.readUInt64();
@ -1636,7 +1636,7 @@ void SocialHandler::handlePetitionShowSignatures(network::Packet& packet) {
}
void SocialHandler::handlePetitionSignResults(network::Packet& packet) {
auto rem = [&]() { return packet.getSize() - packet.getReadPos(); };
auto rem = [&]() { return packet.getRemainingSize(); };
if (rem() < 20) return;
uint64_t petGuid = packet.readUInt64();
uint64_t playerGuid = packet.readUInt64();
@ -1719,13 +1719,13 @@ void SocialHandler::handleWho(network::Packet& packet) {
if (packet.getReadPos() >= packet.getSize()) break;
std::string playerName = packet.readString();
std::string guildName = packet.readString();
if (packet.getSize() - packet.getReadPos() < 12) break;
if (!packet.hasRemaining(12)) break;
uint32_t level = packet.readUInt32();
uint32_t classId = packet.readUInt32();
uint32_t raceId = packet.readUInt32();
if (hasGender && packet.getSize() - packet.getReadPos() >= 1) packet.readUInt8();
if (hasGender && packet.hasRemaining(1)) packet.readUInt8();
uint32_t zoneId = 0;
if (packet.getSize() - packet.getReadPos() >= 4) zoneId = packet.readUInt32();
if (packet.hasRemaining(4)) zoneId = packet.readUInt32();
WhoEntry entry;
entry.name = playerName; entry.guildName = guildName;
entry.level = level; entry.classId = classId;
@ -1739,7 +1739,7 @@ void SocialHandler::handleWho(network::Packet& packet) {
// ============================================================
void SocialHandler::handleFriendList(network::Packet& packet) {
auto rem = [&]() { return packet.getSize() - packet.getReadPos(); };
auto rem = [&]() { return packet.getRemainingSize(); };
if (rem() < 1) return;
uint8_t count = packet.readUInt8();
owner_.contacts_.erase(std::remove_if(owner_.contacts_.begin(), owner_.contacts_.end(),
@ -1771,7 +1771,7 @@ void SocialHandler::handleFriendList(network::Packet& packet) {
}
void SocialHandler::handleContactList(network::Packet& packet) {
auto rem = [&]() { return packet.getSize() - packet.getReadPos(); };
auto rem = [&]() { return packet.getRemainingSize(); };
if (rem() < 8) { packet.setReadPos(packet.getSize()); return; }
owner_.lastContactListMask_ = packet.readUInt32();
owner_.lastContactListCount_ = packet.readUInt32();
@ -1898,27 +1898,27 @@ void SocialHandler::handleLogoutComplete(network::Packet& /*packet*/) {
// ============================================================
void SocialHandler::handleBattlefieldStatus(network::Packet& packet) {
if (packet.getSize() - packet.getReadPos() < 4) return;
if (!packet.hasRemaining(4)) return;
uint32_t queueSlot = packet.readUInt32();
const bool classicFormat = isClassicLikeExpansion();
uint8_t arenaType = 0;
if (!classicFormat) {
if (packet.getSize() - packet.getReadPos() < 1) return;
if (!packet.hasRemaining(1)) return;
arenaType = packet.readUInt8();
if (packet.getSize() - packet.getReadPos() < 1) return;
if (!packet.hasRemaining(1)) return;
packet.readUInt8();
} else {
if (packet.getSize() - packet.getReadPos() < 4) return;
if (!packet.hasRemaining(4)) return;
}
if (packet.getSize() - packet.getReadPos() < 4) return;
if (!packet.hasRemaining(4)) return;
uint32_t bgTypeId = packet.readUInt32();
if (packet.getSize() - packet.getReadPos() < 2) return;
if (!packet.hasRemaining(2)) return;
packet.readUInt16();
if (packet.getSize() - packet.getReadPos() < 4) return;
if (!packet.hasRemaining(4)) return;
packet.readUInt32(); // instanceId
if (packet.getSize() - packet.getReadPos() < 1) return;
if (!packet.hasRemaining(1)) return;
packet.readUInt8(); // isRated
if (packet.getSize() - packet.getReadPos() < 4) return;
if (!packet.hasRemaining(4)) return;
uint32_t statusId = packet.readUInt32();
static const std::pair<uint32_t, const char*> kBgNames[] = {
@ -1936,12 +1936,12 @@ void SocialHandler::handleBattlefieldStatus(network::Packet& packet) {
}
uint32_t inviteTimeout = 80, avgWaitSec = 0, timeInQueueSec = 0;
if (statusId == 1 && packet.getSize() - packet.getReadPos() >= 8) {
if (statusId == 1 && packet.hasRemaining(8)) {
avgWaitSec = packet.readUInt32() / 1000; timeInQueueSec = packet.readUInt32() / 1000;
} else if (statusId == 2) {
if (packet.getSize() - packet.getReadPos() >= 4) inviteTimeout = packet.readUInt32();
if (packet.getSize() - packet.getReadPos() >= 4) packet.readUInt32();
} else if (statusId == 3 && packet.getSize() - packet.getReadPos() >= 8) {
if (packet.hasRemaining(4)) inviteTimeout = packet.readUInt32();
if (packet.hasRemaining(4)) packet.readUInt32();
} else if (statusId == 3 && packet.hasRemaining(8)) {
packet.readUInt32(); packet.readUInt32();
}
@ -1966,19 +1966,19 @@ void SocialHandler::handleBattlefieldStatus(network::Packet& packet) {
}
void SocialHandler::handleBattlefieldList(network::Packet& packet) {
if (packet.getSize() - packet.getReadPos() < 5) return;
if (!packet.hasRemaining(5)) return;
AvailableBgInfo info;
info.bgTypeId = packet.readUInt32();
info.isRegistered = packet.readUInt8() != 0;
const bool isWotlk = isActiveExpansion("wotlk");
const bool isTbc = isActiveExpansion("tbc");
if (isTbc || isWotlk) { if (packet.getSize() - packet.getReadPos() < 1) return; info.isHoliday = packet.readUInt8() != 0; }
if (isWotlk) { if (packet.getSize() - packet.getReadPos() < 8) return; info.minLevel = packet.readUInt32(); info.maxLevel = packet.readUInt32(); }
if (packet.getSize() - packet.getReadPos() < 4) return;
if (isTbc || isWotlk) { if (!packet.hasRemaining(1)) return; info.isHoliday = packet.readUInt8() != 0; }
if (isWotlk) { if (!packet.hasRemaining(8)) return; info.minLevel = packet.readUInt32(); info.maxLevel = packet.readUInt32(); }
if (!packet.hasRemaining(4)) return;
uint32_t count = std::min(packet.readUInt32(), 256u);
info.instanceIds.reserve(count);
for (uint32_t i = 0; i < count; ++i) {
if (packet.getSize() - packet.getReadPos() < 4) break;
if (!packet.hasRemaining(4)) break;
info.instanceIds.push_back(packet.readUInt32());
}
bool updated = false;
@ -2035,13 +2035,13 @@ void SocialHandler::handleRaidInstanceInfo(network::Packet& packet) {
const bool isTbc = isActiveExpansion("tbc");
const bool isClassic = isClassicLikeExpansion();
const bool useTbcFormat = isTbc || isClassic;
if (packet.getSize() - packet.getReadPos() < 4) return;
if (!packet.hasRemaining(4)) return;
uint32_t count = packet.readUInt32();
instanceLockouts_.clear();
instanceLockouts_.reserve(count);
const size_t kEntrySize = useTbcFormat ? 13 : 18;
for (uint32_t i = 0; i < count; ++i) {
if (packet.getSize() - packet.getReadPos() < kEntrySize) break;
if (packet.getRemainingSize() < kEntrySize) break;
InstanceLockout lo;
lo.mapId = packet.readUInt32(); lo.difficulty = packet.readUInt32();
if (useTbcFormat) { lo.resetTime = packet.readUInt32(); lo.locked = packet.readUInt8() != 0; lo.extended = false; }
@ -2051,7 +2051,7 @@ void SocialHandler::handleRaidInstanceInfo(network::Packet& packet) {
}
void SocialHandler::handleInstanceDifficulty(network::Packet& packet) {
auto rem = [&]() { return packet.getSize() - packet.getReadPos(); };
auto rem = [&]() { return packet.getRemainingSize(); };
if (rem() < 4) return;
uint32_t prevDifficulty = instanceDifficulty_;
instanceDifficulty_ = packet.readUInt32();
@ -2075,7 +2075,7 @@ void SocialHandler::handleInstanceDifficulty(network::Packet& packet) {
// ============================================================
void SocialHandler::handleLfgJoinResult(network::Packet& packet) {
if (packet.getSize() - packet.getReadPos() < 2) return;
if (!packet.hasRemaining(2)) return;
uint8_t result = packet.readUInt8();
uint8_t state = packet.readUInt8();
if (result == 0) {
@ -2092,7 +2092,7 @@ void SocialHandler::handleLfgJoinResult(network::Packet& packet) {
}
void SocialHandler::handleLfgQueueStatus(network::Packet& packet) {
if (packet.getSize() - packet.getReadPos() < 33) return;
if (!packet.hasRemaining(33)) return;
lfgDungeonId_ = packet.readUInt32();
int32_t avgWait = static_cast<int32_t>(packet.readUInt32());
int32_t waitTime = static_cast<int32_t>(packet.readUInt32());
@ -2104,7 +2104,7 @@ void SocialHandler::handleLfgQueueStatus(network::Packet& packet) {
}
void SocialHandler::handleLfgProposalUpdate(network::Packet& packet) {
if (packet.getSize() - packet.getReadPos() < 17) return;
if (!packet.hasRemaining(17)) return;
uint32_t dungeonId = packet.readUInt32();
uint32_t proposalId = packet.readUInt32();
uint32_t proposalState = packet.readUInt32();
@ -2124,7 +2124,7 @@ void SocialHandler::handleLfgProposalUpdate(network::Packet& packet) {
}
void SocialHandler::handleLfgRoleCheckUpdate(network::Packet& packet) {
if (packet.getSize() - packet.getReadPos() < 6) return;
if (!packet.hasRemaining(6)) return;
packet.readUInt32();
uint8_t roleCheckState = packet.readUInt8();
packet.readUInt8();
@ -2134,10 +2134,10 @@ void SocialHandler::handleLfgRoleCheckUpdate(network::Packet& packet) {
}
void SocialHandler::handleLfgUpdatePlayer(network::Packet& packet) {
if (packet.getSize() - packet.getReadPos() < 1) return;
if (!packet.hasRemaining(1)) return;
uint8_t updateType = packet.readUInt8();
bool hasExtra = (updateType != 0 && updateType != 1 && updateType != 15 && updateType != 17 && updateType != 18);
if (!hasExtra || packet.getSize() - packet.getReadPos() < 3) {
if (!hasExtra || !packet.hasRemaining(3)) {
switch (updateType) {
case 8: lfgState_ = LfgState::None; owner_.addSystemChatMessage("Dungeon Finder: Removed from queue."); break;
case 9: lfgState_ = LfgState::Queued; owner_.addSystemChatMessage("Dungeon Finder: Proposal failed — re-queuing."); break;
@ -2149,9 +2149,9 @@ void SocialHandler::handleLfgUpdatePlayer(network::Packet& packet) {
return;
}
packet.readUInt8(); packet.readUInt8(); packet.readUInt8();
if (packet.getSize() - packet.getReadPos() >= 1) {
if (packet.hasRemaining(1)) {
uint8_t count = packet.readUInt8();
for (uint8_t i = 0; i < count && packet.getSize() - packet.getReadPos() >= 4; ++i) {
for (uint8_t i = 0; i < count && packet.getRemainingSize() >= 4; ++i) {
uint32_t dungeonEntry = packet.readUInt32();
if (i == 0) lfgDungeonId_ = dungeonEntry;
}
@ -2221,7 +2221,7 @@ void SocialHandler::handleLfgBootProposalUpdate(network::Packet& packet) {
}
void SocialHandler::handleLfgTeleportDenied(network::Packet& packet) {
if (packet.getSize() - packet.getReadPos() < 1) return;
if (!packet.hasRemaining(1)) return;
uint8_t reason = packet.readUInt8();
owner_.addSystemChatMessage(std::string("Dungeon Finder: ") + lfgTeleportDeniedString(reason));
}
@ -2283,7 +2283,7 @@ void SocialHandler::lfgSetBootVote(bool vote) {
// ============================================================
void SocialHandler::handleArenaTeamCommandResult(network::Packet& packet) {
if (packet.getSize() - packet.getReadPos() < 8) return;
if (!packet.hasRemaining(8)) return;
uint32_t command = packet.readUInt32();
std::string name = packet.readString();
uint32_t error = packet.readUInt32();
@ -2294,30 +2294,30 @@ void SocialHandler::handleArenaTeamCommandResult(network::Packet& packet) {
}
void SocialHandler::handleArenaTeamQueryResponse(network::Packet& packet) {
if (packet.getSize() - packet.getReadPos() < 4) return;
if (!packet.hasRemaining(4)) return;
uint32_t teamId = packet.readUInt32();
std::string teamName = packet.readString();
uint32_t teamType = 0;
if (packet.getSize() - packet.getReadPos() >= 4) teamType = packet.readUInt32();
if (packet.hasRemaining(4)) teamType = packet.readUInt32();
for (auto& s : arenaTeamStats_) { if (s.teamId == teamId) { s.teamName = teamName; s.teamType = teamType; return; } }
ArenaTeamStats stub; stub.teamId = teamId; stub.teamName = teamName; stub.teamType = teamType;
arenaTeamStats_.push_back(std::move(stub));
}
void SocialHandler::handleArenaTeamRoster(network::Packet& packet) {
if (packet.getSize() - packet.getReadPos() < 9) return;
if (!packet.hasRemaining(9)) return;
uint32_t teamId = packet.readUInt32();
packet.readUInt8();
uint32_t memberCount = std::min(packet.readUInt32(), 100u);
ArenaTeamRoster roster; roster.teamId = teamId; roster.members.reserve(memberCount);
for (uint32_t i = 0; i < memberCount; ++i) {
if (packet.getSize() - packet.getReadPos() < 12) break;
if (!packet.hasRemaining(12)) break;
ArenaTeamMember m;
m.guid = packet.readUInt64(); m.online = (packet.readUInt8() != 0); m.name = packet.readString();
if (packet.getSize() - packet.getReadPos() < 20) break;
if (!packet.hasRemaining(20)) break;
m.weekGames = packet.readUInt32(); m.weekWins = packet.readUInt32();
m.seasonGames = packet.readUInt32(); m.seasonWins = packet.readUInt32(); m.personalRating = packet.readUInt32();
if (packet.getSize() - packet.getReadPos() >= 8) { packet.readFloat(); packet.readFloat(); }
if (packet.hasRemaining(8)) { packet.readFloat(); packet.readFloat(); }
roster.members.push_back(std::move(m));
}
for (auto& r : arenaTeamRosters_) { if (r.teamId == teamId) { r = std::move(roster); return; } }
@ -2331,10 +2331,10 @@ void SocialHandler::handleArenaTeamInvite(network::Packet& packet) {
}
void SocialHandler::handleArenaTeamEvent(network::Packet& packet) {
if (packet.getSize() - packet.getReadPos() < 1) return;
if (!packet.hasRemaining(1)) return;
uint8_t event = packet.readUInt8();
uint8_t strCount = 0;
if (packet.getSize() - packet.getReadPos() >= 1) strCount = packet.readUInt8();
if (packet.hasRemaining(1)) strCount = packet.readUInt8();
std::string param1, param2;
if (strCount >= 1 && packet.getSize() > packet.getReadPos()) param1 = packet.readString();
if (strCount >= 2 && packet.getSize() > packet.getReadPos()) param2 = packet.readString();
@ -2352,7 +2352,7 @@ void SocialHandler::handleArenaTeamEvent(network::Packet& packet) {
}
void SocialHandler::handleArenaTeamStats(network::Packet& packet) {
if (packet.getSize() - packet.getReadPos() < 28) return;
if (!packet.hasRemaining(28)) return;
ArenaTeamStats stats;
stats.teamId = packet.readUInt32(); stats.rating = packet.readUInt32();
stats.weekGames = packet.readUInt32(); stats.weekWins = packet.readUInt32();
@ -2372,7 +2372,7 @@ void SocialHandler::requestArenaTeamRoster(uint32_t teamId) {
}
void SocialHandler::handleArenaError(network::Packet& packet) {
if (packet.getSize() - packet.getReadPos() < 4) return;
if (!packet.hasRemaining(4)) return;
uint32_t error = packet.readUInt32();
std::string msg;
switch (error) {
@ -2386,7 +2386,7 @@ void SocialHandler::handleArenaError(network::Packet& packet) {
}
void SocialHandler::handlePvpLogData(network::Packet& packet) {
auto remaining = [&]() { return packet.getSize() - packet.getReadPos(); };
auto remaining = [&]() { return packet.getRemainingSize(); };
if (remaining() < 1) return;
bgScoreboard_ = BgScoreboardData{};
bgScoreboard_.isArena = (packet.readUInt8() != 0);

View file

@ -1045,16 +1045,16 @@ void SpellHandler::handleSpellGo(network::Packet& packet) {
void SpellHandler::handleSpellCooldown(network::Packet& packet) {
const bool isClassicFormat = isClassicLikeExpansion();
if (packet.getSize() - packet.getReadPos() < 8) return;
if (!packet.hasRemaining(8)) return;
/*guid*/ packet.readUInt64();
if (!isClassicFormat) {
if (packet.getSize() - packet.getReadPos() < 1) return;
if (!packet.hasRemaining(1)) return;
/*flags*/ packet.readUInt8();
}
const size_t entrySize = isClassicFormat ? 12u : 8u;
while (packet.getSize() - packet.getReadPos() >= entrySize) {
while (packet.getRemainingSize() >= entrySize) {
uint32_t spellId = packet.readUInt32();
uint32_t cdItemId = 0;
if (isClassicFormat) cdItemId = packet.readUInt32();
@ -1099,9 +1099,9 @@ void SpellHandler::handleSpellCooldown(network::Packet& packet) {
}
void SpellHandler::handleCooldownEvent(network::Packet& packet) {
if (packet.getSize() - packet.getReadPos() < 4) return;
if (!packet.hasRemaining(4)) return;
uint32_t spellId = packet.readUInt32();
if (packet.getSize() - packet.getReadPos() >= 8)
if (packet.hasRemaining(8))
packet.readUInt64();
spellCooldowns_.erase(spellId);
for (auto& slot : owner_.actionBar) {
@ -1171,7 +1171,7 @@ void SpellHandler::handleAuraUpdate(network::Packet& packet, bool isAll) {
void SpellHandler::handleLearnedSpell(network::Packet& packet) {
const bool classicSpellId = isClassicLikeExpansion();
const size_t minSz = classicSpellId ? 2u : 4u;
if (packet.getSize() - packet.getReadPos() < minSz) return;
if (packet.getRemainingSize() < minSz) return;
uint32_t spellId = classicSpellId ? packet.readUInt16() : packet.readUInt32();
const bool alreadyKnown = knownSpells_.count(spellId) > 0;
@ -1218,7 +1218,7 @@ void SpellHandler::handleLearnedSpell(network::Packet& packet) {
void SpellHandler::handleRemovedSpell(network::Packet& packet) {
const bool classicSpellId = isClassicLikeExpansion();
const size_t minSz = classicSpellId ? 2u : 4u;
if (packet.getSize() - packet.getReadPos() < minSz) return;
if (packet.getRemainingSize() < minSz) return;
uint32_t spellId = classicSpellId ? packet.readUInt16() : packet.readUInt32();
knownSpells_.erase(spellId);
LOG_INFO("Removed spell: ", spellId);
@ -1243,7 +1243,7 @@ void SpellHandler::handleRemovedSpell(network::Packet& packet) {
void SpellHandler::handleSupercededSpell(network::Packet& packet) {
const bool classicSpellId = isClassicLikeExpansion();
const size_t minSz = classicSpellId ? 4u : 8u;
if (packet.getSize() - packet.getReadPos() < minSz) return;
if (packet.getRemainingSize() < minSz) return;
uint32_t oldSpellId = classicSpellId ? packet.readUInt16() : packet.readUInt32();
uint32_t newSpellId = classicSpellId ? packet.readUInt16() : packet.readUInt32();
@ -1279,12 +1279,12 @@ void SpellHandler::handleSupercededSpell(network::Packet& packet) {
}
void SpellHandler::handleUnlearnSpells(network::Packet& packet) {
if (packet.getSize() - packet.getReadPos() < 4) return;
if (!packet.hasRemaining(4)) return;
uint32_t spellCount = packet.readUInt32();
LOG_INFO("Unlearning ", spellCount, " spells");
bool barChanged = false;
for (uint32_t i = 0; i < spellCount && packet.getSize() - packet.getReadPos() >= 4; ++i) {
for (uint32_t i = 0; i < spellCount && packet.getRemainingSize() >= 4; ++i) {
uint32_t spellId = packet.readUInt32();
knownSpells_.erase(spellId);
LOG_INFO(" Unlearned spell: ", spellId);
@ -1303,12 +1303,12 @@ void SpellHandler::handleUnlearnSpells(network::Packet& packet) {
}
void SpellHandler::handleTalentsInfo(network::Packet& packet) {
if (packet.getSize() - packet.getReadPos() < 1) return;
if (!packet.hasRemaining(1)) return;
uint8_t talentType = packet.readUInt8();
if (talentType != 0) {
return;
}
if (packet.getSize() - packet.getReadPos() < 6) {
if (!packet.hasRemaining(6)) {
LOG_WARNING("handleTalentsInfo: packet too short for header");
return;
}
@ -1323,20 +1323,20 @@ void SpellHandler::handleTalentsInfo(network::Packet& packet) {
activeTalentSpec_ = activeTalentGroup;
for (uint8_t g = 0; g < talentGroupCount && g < 2; ++g) {
if (packet.getSize() - packet.getReadPos() < 1) break;
if (!packet.hasRemaining(1)) break;
uint8_t talentCount = packet.readUInt8();
learnedTalents_[g].clear();
for (uint8_t t = 0; t < talentCount; ++t) {
if (packet.getSize() - packet.getReadPos() < 5) break;
if (!packet.hasRemaining(5)) break;
uint32_t talentId = packet.readUInt32();
uint8_t rank = packet.readUInt8();
learnedTalents_[g][talentId] = rank + 1u;
}
learnedGlyphs_[g].fill(0);
if (packet.getSize() - packet.getReadPos() < 1) break;
if (!packet.hasRemaining(1)) break;
uint8_t glyphCount = packet.readUInt8();
for (uint8_t gl = 0; gl < glyphCount; ++gl) {
if (packet.getSize() - packet.getReadPos() < 2) break;
if (!packet.hasRemaining(2)) break;
uint16_t glyphId = packet.readUInt16();
if (gl < MAX_GLYPH_SLOTS) learnedGlyphs_[g][gl] = glyphId;
}
@ -1365,7 +1365,7 @@ void SpellHandler::handleTalentsInfo(network::Packet& packet) {
}
void SpellHandler::handleAchievementEarned(network::Packet& packet) {
size_t remaining = packet.getSize() - packet.getReadPos();
size_t remaining = packet.getRemainingSize();
if (remaining < 16) return;
uint64_t guid = packet.readUInt64();