From a2eaf3965a2ab142a60eaa150375f60a0c0a0ab1 Mon Sep 17 00:00:00 2001 From: Kelsi Date: Wed, 6 May 2026 05:34:41 -0700 Subject: [PATCH] fix(wom): clamp out-of-range indices + reject absurd texture path lengths MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Out-of-range indices were a silent vector overrun on the GPU side that could crash the vertex shader on some drivers. Replace with 0 rather than dropping so triangle counts stay aligned (a degenerate triangle is harmless, an off-by-one indexing the wrong vertex is silent corruption). Texture path length over 1KB is almost certainly a corrupted or truncated file — was previously read into a 65KB-string allocation per entry which could exhaust memory on a malicious file. --- src/pipeline/wowee_model.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/pipeline/wowee_model.cpp b/src/pipeline/wowee_model.cpp index 04e03ef4..79d4649d 100644 --- a/src/pipeline/wowee_model.cpp +++ b/src/pipeline/wowee_model.cpp @@ -89,10 +89,20 @@ WoweeModel WoweeModelLoader::load(const std::string& basePath) { model.indices.resize(indexCount); f.read(reinterpret_cast(model.indices.data()), indexCount * 4); + // Clamp out-of-range indices — these would index past the vertex buffer + // and crash the GPU vertex shader. Replace with 0 rather than drop, so + // triangle counts stay aligned (a degenerate triangle is harmless, + // an off-by-one indexing the wrong vertex is silent corruption). + const uint32_t vMax = vertCount > 0 ? vertCount - 1 : 0; + for (auto& idx : model.indices) { + if (idx > vMax) idx = 0; + } 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; } std::string path(pathLen, '\0'); f.read(path.data(), pathLen); model.texturePaths.push_back(path);