mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-04-17 17:43:52 +00:00
Add packet size validation to SMSG_CREATURE_QUERY_RESPONSE parsing
Improve robustness of creature query response parsing by adding defensive size checks to both WotLK/TBC and Classic variants: - WotLK/TBC (world_packets.cpp): Add upfront validation for entry field, validate minimum size (16 bytes) before reading fixed fields (typeFlags, creatureType, family, rank), graceful truncation handling - Classic (packet_parsers_classic.cpp): Add upfront entry validation, enhance existing truncation check with default field initialization, improve logging consistency - Both variants now initialize fields to 0 on truncation and log warnings with entry context Part of ongoing Tier 2 work to improve multi-expansion packet parsing robustness against malformed or truncated server packets.
This commit is contained in:
parent
e464300346
commit
2f1b142e14
2 changed files with 31 additions and 3 deletions
|
|
@ -1755,6 +1755,12 @@ network::Packet ClassicPacketParsers::buildAcceptQuestPacket(uint64_t npcGuid, u
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
bool ClassicPacketParsers::parseCreatureQueryResponse(network::Packet& packet,
|
bool ClassicPacketParsers::parseCreatureQueryResponse(network::Packet& packet,
|
||||||
CreatureQueryResponseData& data) {
|
CreatureQueryResponseData& data) {
|
||||||
|
// Validate minimum packet size: entry(4)
|
||||||
|
if (packet.getSize() < 4) {
|
||||||
|
LOG_ERROR("Classic SMSG_CREATURE_QUERY_RESPONSE: packet too small (", packet.getSize(), " bytes)");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
data.entry = packet.readUInt32();
|
data.entry = packet.readUInt32();
|
||||||
if (data.entry & 0x80000000) {
|
if (data.entry & 0x80000000) {
|
||||||
data.entry &= ~0x80000000;
|
data.entry &= ~0x80000000;
|
||||||
|
|
@ -1769,15 +1775,19 @@ bool ClassicPacketParsers::parseCreatureQueryResponse(network::Packet& packet,
|
||||||
data.subName = packet.readString();
|
data.subName = packet.readString();
|
||||||
// NOTE: NO iconName field in Classic 1.12 — goes straight to typeFlags
|
// NOTE: NO iconName field in Classic 1.12 — goes straight to typeFlags
|
||||||
if (packet.getReadPos() + 16 > packet.getSize()) {
|
if (packet.getReadPos() + 16 > packet.getSize()) {
|
||||||
LOG_WARNING("[Classic] Creature query: truncated at typeFlags (entry=", data.entry, ")");
|
LOG_WARNING("Classic SMSG_CREATURE_QUERY_RESPONSE: truncated at typeFlags (entry=", data.entry, ")");
|
||||||
return true;
|
data.typeFlags = 0;
|
||||||
|
data.creatureType = 0;
|
||||||
|
data.family = 0;
|
||||||
|
data.rank = 0;
|
||||||
|
return true; // Have name/sub fields; base fields are important but optional
|
||||||
}
|
}
|
||||||
data.typeFlags = packet.readUInt32();
|
data.typeFlags = packet.readUInt32();
|
||||||
data.creatureType = packet.readUInt32();
|
data.creatureType = packet.readUInt32();
|
||||||
data.family = packet.readUInt32();
|
data.family = packet.readUInt32();
|
||||||
data.rank = packet.readUInt32();
|
data.rank = packet.readUInt32();
|
||||||
|
|
||||||
LOG_DEBUG("[Classic] Creature query: ", data.name, " type=", data.creatureType,
|
LOG_DEBUG("Classic SMSG_CREATURE_QUERY_RESPONSE: ", data.name, " type=", data.creatureType,
|
||||||
" rank=", data.rank);
|
" rank=", data.rank);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2295,6 +2295,12 @@ network::Packet CreatureQueryPacket::build(uint32_t entry, uint64_t guid) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CreatureQueryResponseParser::parse(network::Packet& packet, CreatureQueryResponseData& data) {
|
bool CreatureQueryResponseParser::parse(network::Packet& packet, CreatureQueryResponseData& data) {
|
||||||
|
// Validate minimum packet size: entry(4)
|
||||||
|
if (packet.getSize() < 4) {
|
||||||
|
LOG_ERROR("SMSG_CREATURE_QUERY_RESPONSE: packet too small (", packet.getSize(), " bytes)");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
data.entry = packet.readUInt32();
|
data.entry = packet.readUInt32();
|
||||||
|
|
||||||
// High bit set means creature not found
|
// High bit set means creature not found
|
||||||
|
|
@ -2312,6 +2318,18 @@ bool CreatureQueryResponseParser::parse(network::Packet& packet, CreatureQueryRe
|
||||||
packet.readString(); // name4
|
packet.readString(); // name4
|
||||||
data.subName = packet.readString();
|
data.subName = packet.readString();
|
||||||
data.iconName = packet.readString();
|
data.iconName = packet.readString();
|
||||||
|
|
||||||
|
// WotLK: 4 fixed fields after iconName (typeFlags, creatureType, family, rank)
|
||||||
|
// Validate minimum size for these fields: 4×4 = 16 bytes
|
||||||
|
if (packet.getSize() - packet.getReadPos() < 16) {
|
||||||
|
LOG_WARNING("SMSG_CREATURE_QUERY_RESPONSE: truncated before typeFlags (entry=", data.entry, ")");
|
||||||
|
data.typeFlags = 0;
|
||||||
|
data.creatureType = 0;
|
||||||
|
data.family = 0;
|
||||||
|
data.rank = 0;
|
||||||
|
return true; // Have name/sub/icon; base fields are important but optional
|
||||||
|
}
|
||||||
|
|
||||||
data.typeFlags = packet.readUInt32();
|
data.typeFlags = packet.readUInt32();
|
||||||
data.creatureType = packet.readUInt32();
|
data.creatureType = packet.readUInt32();
|
||||||
data.family = packet.readUInt32();
|
data.family = packet.readUInt32();
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue