summaryrefslogtreecommitdiff
path: root/Source/Core/Common/ChunkFile.h
diff options
context:
space:
mode:
authorAdmiral H. Curtiss <pikachu025@gmail.com>2022-04-18 04:13:25 +0200
committerAdmiral H. Curtiss <pikachu025@gmail.com>2022-04-18 23:48:00 +0200
commitef760ee012a1a7a9d8997fecce4f0c9a7122e1bd (patch)
tree1e97fada9f3c2a759a5d6b78353fee2ad051385b /Source/Core/Common/ChunkFile.h
parent853cf4f8181dd0162e81ebcd61331d8765d089ca (diff)
Common/PointerWrap: Prevent reads/writes past the end of the buffer.
Diffstat (limited to 'Source/Core/Common/ChunkFile.h')
-rw-r--r--Source/Core/Common/ChunkFile.h34
1 files changed, 25 insertions, 9 deletions
diff --git a/Source/Core/Common/ChunkFile.h b/Source/Core/Common/ChunkFile.h
index e7791839db..9fd785459e 100644
--- a/Source/Core/Common/ChunkFile.h
+++ b/Source/Core/Common/ChunkFile.h
@@ -47,11 +47,16 @@ public:
};
private:
- u8** ptr;
+ u8** m_ptr_current;
+ u8* m_ptr_end;
Mode mode;
public:
- PointerWrap(u8** ptr_, Mode mode_) : ptr(ptr_), mode(mode_) {}
+ PointerWrap(u8** ptr, size_t size, Mode mode_)
+ : m_ptr_current(ptr), m_ptr_end(*ptr + size), mode(mode_)
+ {
+ }
+
void SetMode(Mode mode_) { mode = mode_; }
Mode GetMode() const { return mode; }
template <typename K, class V>
@@ -209,8 +214,13 @@ public:
[[nodiscard]] u8* DoExternal(u32& count)
{
Do(count);
- u8* current = *ptr;
- *ptr += count;
+ u8* current = *m_ptr_current;
+ *m_ptr_current += count;
+ if (mode != MODE_MEASURE && *m_ptr_current > m_ptr_end)
+ {
+ // trying to read/write past the end of the buffer, prevent this
+ mode = MODE_MEASURE;
+ }
return current;
}
@@ -320,26 +330,32 @@ private:
DOLPHIN_FORCE_INLINE void DoVoid(void* data, u32 size)
{
+ if (mode != MODE_MEASURE && (*m_ptr_current + size) > m_ptr_end)
+ {
+ // trying to read/write past the end of the buffer, prevent this
+ mode = MODE_MEASURE;
+ }
+
switch (mode)
{
case MODE_READ:
- memcpy(data, *ptr, size);
+ memcpy(data, *m_ptr_current, size);
break;
case MODE_WRITE:
- memcpy(*ptr, data, size);
+ memcpy(*m_ptr_current, data, size);
break;
case MODE_MEASURE:
break;
case MODE_VERIFY:
- DEBUG_ASSERT_MSG(COMMON, !memcmp(data, *ptr, size),
+ DEBUG_ASSERT_MSG(COMMON, !memcmp(data, *m_ptr_current, size),
"Savestate verification failure: buf {} != {} (size {}).\n", fmt::ptr(data),
- fmt::ptr(*ptr), size);
+ fmt::ptr(*m_ptr_current), size);
break;
}
- *ptr += size;
+ *m_ptr_current += size;
}
};