Common/PointerWrap: Prevent reads/writes past the end of the buffer.

This commit is contained in:
Admiral H. Curtiss
2022-04-18 04:13:25 +02:00
parent 853cf4f818
commit ef760ee012
4 changed files with 51 additions and 27 deletions

View File

@ -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;
}
};