From 19b62032727600b6aeeca9d7be53e4b145cd1cf9 Mon Sep 17 00:00:00 2001 From: momo5502 Date: Mon, 20 Mar 2017 21:07:55 +0100 Subject: [PATCH] [IGfxWorld] Fix runtime data overflow --- src/Components/Modules/AssetInterfaces/IGfxImage.cpp | 5 +++++ src/Components/Modules/AssetInterfaces/IGfxWorld.cpp | 12 ++++++------ src/Components/Modules/AssetInterfaces/IGfxWorld.hpp | 2 +- src/Components/Modules/ZoneBuilder.cpp | 5 +++++ src/Utils/CSV.cpp | 2 +- src/Utils/Stream.cpp | 5 +++++ src/Utils/Stream.hpp | 1 + 7 files changed, 24 insertions(+), 8 deletions(-) diff --git a/src/Components/Modules/AssetInterfaces/IGfxImage.cpp b/src/Components/Modules/AssetInterfaces/IGfxImage.cpp index 5d7c153c..428288e2 100644 --- a/src/Components/Modules/AssetInterfaces/IGfxImage.cpp +++ b/src/Components/Modules/AssetInterfaces/IGfxImage.cpp @@ -52,6 +52,11 @@ namespace Assets image->loaded = true; image->loadDef->flags = 0; + if(image->loadDef->resourceSize != image->dataLen1) + { + Components::Logger::Error("Resource size doesn't match the data length (%s)!\n", name.data()); + } + if (Utils::String::StartsWith(name, "*lightmap")) { image->loadDef->dimensions[0] = 0; diff --git a/src/Components/Modules/AssetInterfaces/IGfxWorld.cpp b/src/Components/Modules/AssetInterfaces/IGfxWorld.cpp index 1ae642dd..a3b0f918 100644 --- a/src/Components/Modules/AssetInterfaces/IGfxWorld.cpp +++ b/src/Components/Modules/AssetInterfaces/IGfxWorld.cpp @@ -909,7 +909,7 @@ namespace Assets SaveLogExit(); } - void IGfxWorld::saveGfxWorldDpvsDynamic(Game::GfxWorldDpvsDynamic* asset, Game::GfxWorldDpvsDynamic* dest, Components::ZoneBuilder::Zone* builder) + void IGfxWorld::saveGfxWorldDpvsDynamic(Game::GfxWorldDpvsDynamic* asset, Game::GfxWorldDpvsDynamic* dest, int cellCount, Components::ZoneBuilder::Zone* builder) { AssertSize(Game::GfxWorldDpvsDynamic, 48); @@ -921,14 +921,14 @@ namespace Assets if (asset->dynEntCellBits[0]) { buffer->align(Utils::Stream::ALIGN_4); - buffer->saveArray(asset->dynEntCellBits[0], asset->dynEntClientWordCount[0]); + buffer->save(asset->dynEntCellBits[0], 4, asset->dynEntClientWordCount[0] * cellCount); Utils::Stream::ClearPointer(&dest->dynEntCellBits[0]); } if (asset->dynEntCellBits[1]) { buffer->align(Utils::Stream::ALIGN_4); - buffer->saveArray(asset->dynEntCellBits[1], asset->dynEntClientWordCount[1]); + buffer->save(asset->dynEntCellBits[1], 4, asset->dynEntClientWordCount[1] * cellCount); Utils::Stream::ClearPointer(&dest->dynEntCellBits[1]); } @@ -1188,14 +1188,14 @@ namespace Assets if (asset->cellCasterBits) { buffer->align(Utils::Stream::ALIGN_4); - buffer->saveArray(asset->cellCasterBits, cellCount * ((cellCount + 31) >> 5)); + buffer->save(asset->cellCasterBits, 4, cellCount * ((cellCount + 31) >> 5)); Utils::Stream::ClearPointer(&dest->cellCasterBits); } if (asset->cellHasSunLitSurfsBits) { buffer->align(Utils::Stream::ALIGN_4); - buffer->saveArray(asset->cellHasSunLitSurfsBits, ((cellCount + 31) >> 5)); + buffer->save(asset->cellHasSunLitSurfsBits, 4, ((cellCount + 31) >> 5)); Utils::Stream::ClearPointer(&dest->cellHasSunLitSurfsBits); } @@ -1332,7 +1332,7 @@ namespace Assets } this->saveGfxWorldDpvsStatic(asset, &asset->dpvs, &dest->dpvs, asset->dpvsPlanes.cellCount, builder); - this->saveGfxWorldDpvsDynamic(&asset->dpvsDyn, &dest->dpvsDyn, builder); + this->saveGfxWorldDpvsDynamic(&asset->dpvsDyn, &dest->dpvsDyn, asset->dpvsPlanes.cellCount, builder); if (asset->heroOnlyLights) { diff --git a/src/Components/Modules/AssetInterfaces/IGfxWorld.hpp b/src/Components/Modules/AssetInterfaces/IGfxWorld.hpp index a6348dc2..8dda2561 100644 --- a/src/Components/Modules/AssetInterfaces/IGfxWorld.hpp +++ b/src/Components/Modules/AssetInterfaces/IGfxWorld.hpp @@ -16,7 +16,7 @@ namespace Assets void saveGfxLightGrid(Game::GfxLightGrid* asset, Game::GfxLightGrid* dest, Components::ZoneBuilder::Zone* builder); void savesunflare_t(Game::sunflare_t* asset, Game::sunflare_t* dest, Components::ZoneBuilder::Zone* builder); void saveGfxWorldDpvsStatic(Game::GfxWorld* world, Game::GfxWorldDpvsStatic* asset, Game::GfxWorldDpvsStatic* dest, int planeCount, Components::ZoneBuilder::Zone* builder); - void saveGfxWorldDpvsDynamic(Game::GfxWorldDpvsDynamic* asset, Game::GfxWorldDpvsDynamic* dest, Components::ZoneBuilder::Zone* builder); + void saveGfxWorldDpvsDynamic(Game::GfxWorldDpvsDynamic* asset, Game::GfxWorldDpvsDynamic* dest, int cellCount, Components::ZoneBuilder::Zone* builder); void loadGfxWorldDraw(Game::GfxWorldDraw* asset, Components::ZoneBuilder::Zone* builder, Utils::Stream::Reader* reader); void loadGfxWorldDpvsStatic(Game::GfxWorld* world, Game::GfxWorldDpvsStatic* asset, Components::ZoneBuilder::Zone* builder, Utils::Stream::Reader* reader); diff --git a/src/Components/Modules/ZoneBuilder.cpp b/src/Components/Modules/ZoneBuilder.cpp index aeb0c60e..6c98c2c5 100644 --- a/src/Components/Modules/ZoneBuilder.cpp +++ b/src/Components/Modules/ZoneBuilder.cpp @@ -98,6 +98,11 @@ namespace Components Logger::Print("Saving...\n"); this->saveData(); + if(this->buffer.hasBlock()) + { + Logger::Error("Non-popped blocks left!\n"); + } + Logger::Print("Compressing...\n"); this->writeZone(); } diff --git a/src/Utils/CSV.cpp b/src/Utils/CSV.cpp index 56785a58..fec7d065 100644 --- a/src/Utils/CSV.cpp +++ b/src/Utils/CSV.cpp @@ -98,7 +98,7 @@ namespace Utils for (unsigned int i = 0; i < row.size(); ++i) { - if (row[i] == ',' && !isString) // FLush entry + if (row[i] == ',' && !isString) // Flush entry { _row.push_back(element); element.clear(); diff --git a/src/Utils/Stream.cpp b/src/Utils/Stream.cpp index 08446e64..ac57f996 100644 --- a/src/Utils/Stream.cpp +++ b/src/Utils/Stream.cpp @@ -246,6 +246,11 @@ namespace Utils return false; } + bool Stream::hasBlock() + { + return !this->streamStack.empty(); + } + bool Stream::isValidBlock(Game::XFILE_BLOCK_TYPES stream) { return (stream < Game::MAX_XFILE_COUNT && stream >= Game::XFILE_BLOCK_TEMP); diff --git a/src/Utils/Stream.hpp b/src/Utils/Stream.hpp index d20758a7..9687dcc8 100644 --- a/src/Utils/Stream.hpp +++ b/src/Utils/Stream.hpp @@ -117,6 +117,7 @@ namespace Utils void increaseBlockSize(unsigned int size); Game::XFILE_BLOCK_TYPES getCurrentBlock(); unsigned int getBlockSize(Game::XFILE_BLOCK_TYPES stream); + bool hasBlock(); DWORD getPackedOffset();