fix(wob+wom): reject corrupted header counts before allocating

Adds upfront sanity bounds to both WoB and WOM load:
  WOM: vert<=1M, index<=4M, tex<=1K
  WOB: groups<=4K, portals<=8K, doodads<=64K
Real WoW models stay well under these limits (M2 vert is uint16 anyway).
Without these checks a corrupted header could trigger a multi-GB
allocation and OOM the process before we finish reading the body. Also
caps name length to 1KB on WoB load (already done on WOM).
This commit is contained in:
Kelsi 2026-05-06 05:42:50 -07:00
parent c05d421c29
commit 90289ba48b
2 changed files with 17 additions and 0 deletions

View file

@ -31,9 +31,18 @@ WoweeBuilding WoweeBuildingLoader::load(const std::string& basePath) {
f.read(reinterpret_cast<char*>(&portalCount), 4);
f.read(reinterpret_cast<char*>(&doodadCount), 4);
f.read(reinterpret_cast<char*>(&bld.boundRadius), 4);
// Sanity bounds. Real WMOs are usually 1-50 groups; >4096 indicates a
// corrupted header that would OOM us when we resize() vectors.
if (groupCount > 4096 || portalCount > 8192 || doodadCount > 65536) {
LOG_ERROR("WOB header rejected (groups=", groupCount,
" portals=", portalCount, " doodads=", doodadCount, "): ", basePath);
return WoweeBuilding{};
}
if (!std::isfinite(bld.boundRadius) || bld.boundRadius < 0.0f) bld.boundRadius = 1.0f;
uint16_t nameLen;
f.read(reinterpret_cast<char*>(&nameLen), 2);
if (nameLen > 1024) nameLen = 0;
bld.name.resize(nameLen);
f.read(bld.name.data(), nameLen);