mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-03-22 23:30:14 +00:00
Add packet size validation to SMSG_GAMEOBJECT_QUERY_RESPONSE parsing
Improve robustness of game object 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, type, displayId fields, and improved in-loop handling for variable-length data array with partial data graceful degradation - Classic (packet_parsers_classic.cpp): Add upfront validation for entry, type, displayId fields, and enhanced in-loop data array read with truncation detection - Both variants now log warnings when data fields are truncated 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
d1414b6a46
commit
73abbc2a08
2 changed files with 44 additions and 0 deletions
|
|
@ -979,6 +979,12 @@ bool ClassicPacketParsers::parseGuildQueryResponse(network::Packet& packet, Guil
|
|||
// ============================================================================
|
||||
|
||||
bool ClassicPacketParsers::parseGameObjectQueryResponse(network::Packet& packet, GameObjectQueryResponseData& data) {
|
||||
// Validate minimum packet size: entry(4)
|
||||
if (packet.getSize() < 4) {
|
||||
LOG_ERROR("Classic SMSG_GAMEOBJECT_QUERY_RESPONSE: packet too small (", packet.getSize(), " bytes)");
|
||||
return false;
|
||||
}
|
||||
|
||||
data.entry = packet.readUInt32();
|
||||
|
||||
// High bit set means gameobject not found
|
||||
|
|
@ -988,6 +994,12 @@ bool ClassicPacketParsers::parseGameObjectQueryResponse(network::Packet& packet,
|
|||
return true;
|
||||
}
|
||||
|
||||
// Validate minimum size for fixed fields: type(4) + displayId(4)
|
||||
if (packet.getSize() - packet.getReadPos() < 8) {
|
||||
LOG_ERROR("Classic SMSG_GAMEOBJECT_QUERY_RESPONSE: truncated before names (entry=", data.entry, ")");
|
||||
return false;
|
||||
}
|
||||
|
||||
data.type = packet.readUInt32();
|
||||
data.displayId = packet.readUInt32();
|
||||
// 4 name strings
|
||||
|
|
@ -1003,6 +1015,16 @@ bool ClassicPacketParsers::parseGameObjectQueryResponse(network::Packet& packet,
|
|||
data.data[i] = packet.readUInt32();
|
||||
}
|
||||
data.hasData = true;
|
||||
} else if (remaining > 0) {
|
||||
// Partial data field; read what we can
|
||||
uint32_t fieldsToRead = remaining / 4;
|
||||
for (uint32_t i = 0; i < fieldsToRead && i < 24; i++) {
|
||||
data.data[i] = packet.readUInt32();
|
||||
}
|
||||
if (fieldsToRead < 24) {
|
||||
LOG_WARNING("Classic SMSG_GAMEOBJECT_QUERY_RESPONSE: truncated in data fields (", fieldsToRead,
|
||||
" of 24 read, entry=", data.entry, ")");
|
||||
}
|
||||
}
|
||||
|
||||
if (data.type == 15) { // MO_TRANSPORT
|
||||
|
|
|
|||
|
|
@ -2336,6 +2336,12 @@ network::Packet GameObjectQueryPacket::build(uint32_t entry, uint64_t guid) {
|
|||
}
|
||||
|
||||
bool GameObjectQueryResponseParser::parse(network::Packet& packet, GameObjectQueryResponseData& data) {
|
||||
// Validate minimum packet size: entry(4)
|
||||
if (packet.getSize() < 4) {
|
||||
LOG_ERROR("SMSG_GAMEOBJECT_QUERY_RESPONSE: packet too small (", packet.getSize(), " bytes)");
|
||||
return false;
|
||||
}
|
||||
|
||||
data.entry = packet.readUInt32();
|
||||
|
||||
// High bit set means gameobject not found
|
||||
|
|
@ -2346,6 +2352,12 @@ bool GameObjectQueryResponseParser::parse(network::Packet& packet, GameObjectQue
|
|||
return true;
|
||||
}
|
||||
|
||||
// Validate minimum size for fixed fields: type(4) + displayId(4)
|
||||
if (packet.getSize() - packet.getReadPos() < 8) {
|
||||
LOG_ERROR("SMSG_GAMEOBJECT_QUERY_RESPONSE: truncated before names (entry=", data.entry, ")");
|
||||
return false;
|
||||
}
|
||||
|
||||
data.type = packet.readUInt32(); // GameObjectType
|
||||
data.displayId = packet.readUInt32();
|
||||
// 4 name strings (only first is usually populated)
|
||||
|
|
@ -2367,6 +2379,16 @@ bool GameObjectQueryResponseParser::parse(network::Packet& packet, GameObjectQue
|
|||
data.data[i] = packet.readUInt32();
|
||||
}
|
||||
data.hasData = true;
|
||||
} else if (remaining > 0) {
|
||||
// Partial data field; read what we can
|
||||
uint32_t fieldsToRead = remaining / 4;
|
||||
for (uint32_t i = 0; i < fieldsToRead && i < 24; i++) {
|
||||
data.data[i] = packet.readUInt32();
|
||||
}
|
||||
if (fieldsToRead < 24) {
|
||||
LOG_WARNING("SMSG_GAMEOBJECT_QUERY_RESPONSE: truncated in data fields (", fieldsToRead,
|
||||
" of 24 read, entry=", data.entry, ")");
|
||||
}
|
||||
}
|
||||
|
||||
LOG_DEBUG("GameObject query response: ", data.name, " (type=", data.type, " entry=", data.entry, ")");
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue