From c0c1be1c9e77ed19a770f619d9f868609318c989 Mon Sep 17 00:00:00 2001 From: Kelsi Date: Wed, 6 May 2026 05:52:58 -0700 Subject: [PATCH] fix(wob): cap material/doodad path lengths + portal vertex count MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Three more per-record sanity bounds that the per-group sweep didn't cover: - material.texturePath length cap (1KB) — was unbounded - doodad.modelPath length cap (1KB) — was unbounded - portal.vertexCount cap (4096) — real portals are 4-12 verts; >4K is corrupt and would OOM the resize --- src/pipeline/wowee_building.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/pipeline/wowee_building.cpp b/src/pipeline/wowee_building.cpp index 388f38bf..adb43575 100644 --- a/src/pipeline/wowee_building.cpp +++ b/src/pipeline/wowee_building.cpp @@ -112,6 +112,7 @@ WoweeBuilding WoweeBuildingLoader::load(const std::string& basePath) { WoweeBuilding::Material mat; uint16_t pl; f.read(reinterpret_cast(&pl), 2); + if (pl > 1024) pl = 0; mat.texturePath.resize(pl); f.read(mat.texturePath.data(), pl); f.read(reinterpret_cast(&mat.flags), 4); @@ -130,6 +131,11 @@ WoweeBuilding WoweeBuildingLoader::load(const std::string& basePath) { f.read(reinterpret_cast(&portal.groupB), 4); uint32_t pvCount; f.read(reinterpret_cast(&pvCount), 4); + // Real portals are 4-12 vertices; >4096 is corrupt. + if (pvCount > 4096) { + LOG_ERROR("WOB portal ", pi, " vertex count rejected (", pvCount, "): ", basePath); + return WoweeBuilding{}; + } portal.vertices.resize(pvCount); f.read(reinterpret_cast(portal.vertices.data()), pvCount * 12); bld.portals.push_back(portal); @@ -139,6 +145,7 @@ WoweeBuilding WoweeBuildingLoader::load(const std::string& basePath) { WoweeBuilding::DoodadPlacement dp; uint16_t pl; f.read(reinterpret_cast(&pl), 2); + if (pl > 1024) pl = 0; dp.modelPath.resize(pl); f.read(dp.modelPath.data(), pl); f.read(reinterpret_cast(&dp.position), 12);