Browse Source

Validate stash size to avoid in-game corruption

pull/7940/head
staphen 11 months ago committed by Anders Jenbo
parent
commit
887f68e2a7
  1. 30
      Source/loadsave.cpp

30
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 <typename T>
constexpr void Skip(size_t count = 1)
{
@ -2021,6 +2027,21 @@ tl::expected<void, std::string> 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<void, std::string> ConvertLevels(SaveWriter &saveWriter)
@ -2321,8 +2342,10 @@ void LoadStash()
return;
auto version = file.NextLE<uint8_t>();
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<uint32_t>();
@ -2337,6 +2360,11 @@ void LoadStash()
}
auto itemCount = file.NextLE<uint32_t>();
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]);

Loading…
Cancel
Save