From 887f68e2a75afffc29cbb606ac22cc75ff913863 Mon Sep 17 00:00:00 2001 From: staphen Date: Fri, 18 Apr 2025 21:56:06 -0400 Subject: [PATCH] Validate stash size to avoid in-game corruption --- Source/loadsave.cpp | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/Source/loadsave.cpp b/Source/loadsave.cpp index 841c4f562..9f1913c5f 100644 --- a/Source/loadsave.cpp +++ b/Source/loadsave.cpp @@ -35,6 +35,7 @@ #include "mpq/mpq_common.hpp" #include "pfile.h" #include "playerdat.hpp" +#include "plrmsg.h" #include "qol/stash.h" #include "stores.h" #include "utils/algorithm/container.hpp" @@ -128,6 +129,11 @@ public: && m_size_ >= (m_cur_ + size); } + size_t Size() + { + return m_size_; + } + template constexpr void Skip(size_t count = 1) { @@ -2021,6 +2027,21 @@ tl::expected LoadLevel(LevelConversionData *levelConversionDa const int DiabloItemSaveSize = 368; const int HellfireItemSaveSize = 372; +bool IsStashSizeValid(size_t stashSize, uint32_t pages, uint32_t itemCount) +{ + const size_t itemSize = (gbIsHellfire ? HellfireItemSaveSize : DiabloItemSaveSize); + + const size_t expectedSize = sizeof(uint8_t) + + sizeof(uint32_t) + + sizeof(uint32_t) + + (sizeof(uint32_t) + 10 * 10 * sizeof(uint16_t)) * pages + + sizeof(uint32_t) + + itemSize * itemCount + + sizeof(uint32_t); + + return stashSize == expectedSize; +} + } // namespace tl::expected ConvertLevels(SaveWriter &saveWriter) @@ -2321,8 +2342,10 @@ void LoadStash() return; auto version = file.NextLE(); - if (version > StashVersion) + if (version > StashVersion) { + EventPlrMsg(_("Stash version invalid. If you attempt to access your stash, data will be overwritten!!"), UiFlags::ColorRed); return; + } Stash.gold = file.NextLE(); @@ -2337,6 +2360,11 @@ void LoadStash() } auto itemCount = file.NextLE(); + if (!IsStashSizeValid(file.Size(), pages, itemCount)) { + Stash = {}; + EventPlrMsg(_("Stash size invalid. If you attempt to access your stash, data will be overwritten!!"), UiFlags::ColorRed); + return; + } Stash.stashList.resize(itemCount); for (unsigned i = 0; i < itemCount; i++) { LoadAndValidateItemData(file, Stash.stashList[i]);