From 7e2dc4ec1d68ceec455fbd17a012b28dd7d51977 Mon Sep 17 00:00:00 2001 From: Kelsi Date: Wed, 6 May 2026 07:10:53 -0700 Subject: [PATCH] fix(wcp): apply unpack-side header bounds to readInfo + categorize .woc readInfo previously trusted fileCount/infoSize blindly, so a malicious or corrupted WCP could allocate a 4GB string just to print metadata via --info-wcp. Same 1M file / 16MB info caps now applied. Also categorizes .woc collision files (was bucketed under 'other'). --- tools/editor/content_pack.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tools/editor/content_pack.cpp b/tools/editor/content_pack.cpp index f7f91a16..2ad1b5b7 100644 --- a/tools/editor/content_pack.cpp +++ b/tools/editor/content_pack.cpp @@ -195,6 +195,13 @@ bool ContentPacker::readInfo(const std::string& wcpPath, ContentPackInfo& info) uint32_t fileCount, infoSize; in.read(reinterpret_cast(&fileCount), 4); in.read(reinterpret_cast(&infoSize), 4); + // Same sanity bounds as unpack — refuse to allocate or read absurd + // info JSON on a malicious header. + if (fileCount > 1'000'000 || infoSize > 16 * 1024 * 1024) { + LOG_ERROR("WCP readInfo header rejected (fileCount=", fileCount, + " infoSize=", infoSize, "): ", wcpPath); + return false; + } std::string jsonStr(infoSize, '\0'); in.read(jsonStr.data(), infoSize); @@ -219,6 +226,7 @@ bool ContentPacker::readInfo(const std::string& wcpPath, ContentPackInfo& info) if (ext == ".wot" || ext == ".whm") fe.category = "terrain"; else if (ext == ".wom") fe.category = "model"; else if (ext == ".wob") fe.category = "building"; + else if (ext == ".woc") fe.category = "collision"; else if (ext == ".png") fe.category = "texture"; else if (ext == ".json") fe.category = "data"; else if (ext == ".adt" || ext == ".wdt") fe.category = "legacy";