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
@@ -125,7 +125,7 @@ int g_screenshotFailures;
CChunkFileReader::Error LoadFromRam(std::vector<u8> &data, std::string *errorString) {
SaveStart state;
return CChunkFileReader::LoadPtr(&data[0], state, errorString);
return CChunkFileReader::LoadPtr(&data[0], data.size(), state, errorString);
}
// TODO: Should this be configurable?