From bbd2e0502b9ec9d266f15183c5bafb9446e2b7b8 Mon Sep 17 00:00:00 2001 From: Kelsi Date: Wed, 6 May 2026 09:24:55 -0700 Subject: [PATCH] fix(wom): reject load on out-of-range string lengths Same silent-corruption pattern as WoB: model.name had no length check at all (would happily allocate 64KB), and texture paths silently zeroed pathLen on overflow leaving the actual bytes on disk to shift the rest of the file. Now reject with LOG_ERROR. --- src/pipeline/wowee_model.cpp | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/pipeline/wowee_model.cpp b/src/pipeline/wowee_model.cpp index 71e53a2a..66d96c3b 100644 --- a/src/pipeline/wowee_model.cpp +++ b/src/pipeline/wowee_model.cpp @@ -62,6 +62,12 @@ WoweeModel WoweeModelLoader::load(const std::string& basePath) { uint16_t nameLen; f.read(reinterpret_cast(&nameLen), 2); + // Save caps name at 1024; reject anything longer to keep load + // alignment with future-version files predictable. + if (nameLen > 1024) { + LOG_ERROR("WOM name length rejected (", nameLen, "): ", basePath); + return WoweeModel{}; + } model.name.resize(nameLen); f.read(model.name.data(), nameLen); @@ -109,8 +115,14 @@ WoweeModel WoweeModelLoader::load(const std::string& basePath) { for (uint32_t i = 0; i < texCount; i++) { uint16_t pathLen; f.read(reinterpret_cast(&pathLen), 2); - // Reject absurd path lengths (corrupted/truncated file). - if (pathLen > 1024) { pathLen = 0; } + // Same desync risk as elsewhere — pathLen=0 with the actual + // bytes still on disk would shift every subsequent length+data + // pair. Reject the whole load instead of silently dropping. + if (pathLen > 1024) { + LOG_ERROR("WOM texture path ", i, " length rejected (", + pathLen, "): ", basePath); + return WoweeModel{}; + } std::string path(pathLen, '\0'); f.read(path.data(), pathLen); // Reject path-traversal — texture paths from a hostile WOM are fed