Commit Graph
7 Commits
Author SHA1 Message Date
Henrik RydgårdandClaude Opus 5 b42a03e095 Add savestate serializer tests, fix three bounds-check bugs
PointerWrap and the Do() overloads around it are how every savestate is
written and read, and had no direct coverage. Everything read back came off
disk, so the corrupt-input paths matter as much as the round trips.

Three bugs, all in the bounds checking added in 58d4759ceb:

1. sizeof(T) is not a lower bound on how many bytes an element serializes to.
   It only holds for the types DoHelper_ writes out raw. A std::string is 32-40
   bytes in memory and serializes to as few as five; a T* serializes to whatever
   T::DoState() writes. So DoVector/DoList/DoSet/DoMap could reject a perfectly
   valid savestate whenever count * sizeof(element) exceeded the bytes left in
   the buffer. That is not hypothetical: pspFileSystem is serialized dead last
   in SaveStart::DoState, and MetaFileSystem::DoState does Do(p, currentDir) on
   a std::map<int, std::string>, so the check runs with only a few hundred bytes
   remaining and claims 44 bytes per entry against roughly 22 actual. Added
   SerializeMinElemSize<T>(), mirroring DoHelper_'s own condition, and used it
   in all five containers. The bound is only loosened, so nothing that loaded
   before can stop loading.

2. Do(p, std::map<K, T *> &) deletes every value before reading the new ones,
   and DoMap then returned on a bad count without clearing - leaving the map
   full of freed pointers to be used or deleted again. Six live maps go through
   this (sceMpeg, sceMp3, sceAac, sceFont, sceHeap, sceKernelThread's pending
   calls), so a corrupt savestate meant a use-after-free. Clear before the guard
   can bail out, in DoMap, DoMultimap and DoSet.

3. The wstring and u16string overloads validated stringLen < 0 but not 0, and
   didn't require a whole number of characters. read() computes
   stringLen / sizeof(char) - 1, so a length of 0 resized to SIZE_MAX and
   memcpy'd with a wrapped-around size. PSPOskDialog::DoState serializes both
   (inputChars at v2, a legacy wstring below that), so this was reachable: the
   test aborts the process without the fix.

The test covers round trips of PODs, strings (empty, embedded NUL), vector,
map, set, list and map-of-pointers, section titles and version gating in both
directions, marker mismatches, measure-vs-write checkpoint disagreement, the
error latch dropping to MODE_NOOP, every truncation of a valid buffer, and
hand-corrupted counts and lengths.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GZq8ZtJmFY7bkX5FVkr3P9
2026-08-17 14:50:57 +02:00
Henrik RydgårdandClaude Sonnet 5 1eab737e4d Serialize: guard List/Deque/Map/Set against corrupted size fields
DoVector already rejects an attacker/corruption-controlled size that
would resize far beyond what's actually left in the savestate buffer.
DoList/DoDeque/DoMap/DoMultimap/DoSet never got the same treatment -
a corrupted count field (e.g. 0xFFFFFFFF) drove an immediate huge
resize (list/deque) or an unbounded loop of allocations (map/set)
before any per-element bounds checking kicked in. All five now check
the declared count against PointerWrap::Remaining() first.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01L4QAoxV2KY7ek4PcZw3WvY
2026-08-10 01:00:28 +02:00
Herman Semenov 4ef014cb73 [Common] Fixes from Unknown W. Brackets: <checkins@unknownbrackets.org> 2024-09-18 11:11:25 +02:00
Herman Semenov 45429bcd85 [Common/Data/File/Input/Net/Serialize/System/UI] Using for based loop C++17 and replaced on structured binding map C++17 2024-09-17 17:42:08 +02:00
Henrik Rydgård e01ca5b057 Logging API change (refactor) (#19324)
* Rename LogType to Log

* Explicitly use the Log:: enum when logging. Allows for autocomplete when editing.

* Mac/ARM64 buildfix

* Do the same with the hle result log macros

* Rename the log names to mixed case while at it.

* iOS buildfix

* Qt buildfix attempt, ARM32 buildfix
2024-07-14 14:42:59 +02:00
Henrik Rydgård 7e427e41d1 Remove a bunch of dead code from CoreTiming ("threadsafe" events)
We haven't used these "threadsafe" events since we removed our first attempt
at GPU threading, so like 10 years, and maybe some experimentation in the
networking code according to some comments. It's unlikely that any
savestates that used these events would load anyway.
2024-01-16 09:06:03 +01:00
Unknown W. Brackets b8342fb8ec SaveState: Rename ChunkFile files to Serialize.
Makes more sense and less weird than ChunkFileDoMap, etc.
2020-08-10 08:04:05 +00:00