Add bounds checking to savestate deserialization

PointerWrap tracked no end-of-buffer, so DoState() implementations could
read past the end of a crafted or truncated savestate via DoVoid's
unchecked memcpy, and DoVector could resize to an attacker-controlled
size before reading.

- PointerWrap now tracks a read end; DoVoid/ExpectVoid fail (MODE_NOOP)
  before reading out of bounds.
- String reads are bounds-checked for the whole string including NUL.
- DoVector rejects sizes that can't fit in the remaining buffer.
- LoadPtr takes the buffer size and sets the read end.
- Capping the decompression buffer allocation in LoadFile.
This commit is contained in:
Henrik Rydgård committed 2026-08-01 11:57:24 +02:00
1 parent 3ad08377c5
commit 58d4759ceb
5 files changed
+86 -6

No files matched your search

+1 -1
View File
@@ -1802,7 +1802,7 @@ bool retro_unserialize(const void *data, size_t size)
std::string errorString;
SaveState::SaveStart state;
bool retVal = CChunkFileReader::LoadPtr((u8 *)data, state, &errorString)
bool retVal = CChunkFileReader::LoadPtr((u8 *)data, size, state, &errorString)
== CChunkFileReader::ERROR_NONE;
if (useEmuThread)