From 361ff712d73f641c768566a7284e7b88f5897fe0 Mon Sep 17 00:00:00 2001 From: Kelsi Date: Wed, 6 May 2026 06:23:35 -0700 Subject: [PATCH] fix(wob): writeStr helper truncates length-prefixed strings to fit u16 length Without truncation, names over 65535 chars would silently get a wrap- around length value and produce a corrupt file (the actual string would be longer than the saved length, shifting everything after it). Single shared writeStr lambda replaces five copy-pasted (uint16 length + bytes) write blocks. --- src/pipeline/wowee_building.cpp | 31 ++++++++++++++----------------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/src/pipeline/wowee_building.cpp b/src/pipeline/wowee_building.cpp index 02f2fbdb..67696ba4 100644 --- a/src/pipeline/wowee_building.cpp +++ b/src/pipeline/wowee_building.cpp @@ -200,14 +200,19 @@ bool WoweeBuildingLoader::save(const WoweeBuilding& bld, const std::string& base f.write(reinterpret_cast(&dc), 4); f.write(reinterpret_cast(&bld.boundRadius), 4); - uint16_t nl = static_cast(bld.name.size()); - f.write(reinterpret_cast(&nl), 2); - f.write(bld.name.data(), nl); + // Truncate length-prefixed strings to fit their u16 length field — without + // this, names over 65535 chars would silently get a wrap-around length and + // produce a corrupt file (the string text would be longer than the saved + // length and shift everything after it). + auto writeStr = [&](const std::string& s, size_t maxLen = 1024) { + uint16_t len = static_cast(std::min(s.size(), maxLen)); + f.write(reinterpret_cast(&len), 2); + f.write(s.data(), len); + }; + writeStr(bld.name); for (const auto& grp : bld.groups) { - uint16_t gnl = static_cast(grp.name.size()); - f.write(reinterpret_cast(&gnl), 2); - f.write(grp.name.data(), gnl); + writeStr(grp.name); uint32_t vc = static_cast(grp.vertices.size()); uint32_t ic = static_cast(grp.indices.size()); @@ -224,19 +229,13 @@ bool WoweeBuildingLoader::save(const WoweeBuilding& bld, const std::string& base vc * sizeof(WoweeBuilding::Vertex)); f.write(reinterpret_cast(grp.indices.data()), ic * 4); - for (const auto& tp : grp.texturePaths) { - uint16_t tl = static_cast(tp.size()); - f.write(reinterpret_cast(&tl), 2); - f.write(tp.data(), tl); - } + for (const auto& tp : grp.texturePaths) writeStr(tp); // Write material data uint32_t mc = static_cast(grp.materials.size()); f.write(reinterpret_cast(&mc), 4); for (const auto& mat : grp.materials) { - uint16_t pl = static_cast(mat.texturePath.size()); - f.write(reinterpret_cast(&pl), 2); - f.write(mat.texturePath.data(), pl); + writeStr(mat.texturePath); f.write(reinterpret_cast(&mat.flags), 4); f.write(reinterpret_cast(&mat.shader), 4); f.write(reinterpret_cast(&mat.blendMode), 4); @@ -252,9 +251,7 @@ bool WoweeBuildingLoader::save(const WoweeBuilding& bld, const std::string& base } for (const auto& dp : bld.doodads) { - uint16_t pl = static_cast(dp.modelPath.size()); - f.write(reinterpret_cast(&pl), 2); - f.write(dp.modelPath.data(), pl); + writeStr(dp.modelPath); f.write(reinterpret_cast(&dp.position), 12); f.write(reinterpret_cast(&dp.rotation), 12); f.write(reinterpret_cast(&dp.scale), 4);