libretro: relax retro_unserialize size check to permit cross-version state loads
The previous `size != retro_serialize_size()` guard rejected any state whose serialized length didn't exactly match the current build's SFORMAT-derived size. That sounds defensive, but the file format already carries its own 16-byte header with an explicit `totalsize` and `ReadStateChunk()` already skips unknown chunk tags safely (size- bounded `memstream_seek` past the payload), so the outer check adds no parser safety - it just turns every SFORMAT change into a hard break of existing saves with no user recourse. This came up in the recent FDS audio rewrite for #560: the backport added/removed audio-register chunk tags, leaving pre-rewrite states 240 bytes smaller than the new core's expected size, and users with in-progress FDS games hit "unserialize FAIL" on first reload after updating the core. Accept any buffer that's at least the 16-byte header and at most 4x the current serialize size (a sanity cap against pathological input). ReadStateChunk does the actual work of validating each chunk's size against the header's totalsize, and the FCS magic in the header rejects non-fceumm states. Verified on Vs. Excitebike (Japan): - pre-rewrite state -> new core: load OK, audio plays normally - new-rewrite state -> new core: round-trip OK (same audio as before) - 15-byte input: rejected (< header size) - 4 MB input: rejected (> 4 * serialize_size)
This commit is contained in:
committed by
U-DESKTOP-SPFP6AQ\twistedtechre
parent
bc5a7a9fec
commit
fef3de8bd9
@@ -3185,7 +3185,17 @@ bool retro_unserialize(const void * data, size_t size)
|
||||
if (geniestage == 1)
|
||||
return false;
|
||||
|
||||
if (!data || size != retro_serialize_size())
|
||||
/* The state file's own 16-byte header carries an explicit totalsize
|
||||
* and ReadStateChunk already skips unknown chunk tags, so a strict
|
||||
* size-equality check against the current build's serialize_size is
|
||||
* not necessary for parser safety - and is actively harmful when
|
||||
* SFORMAT contents change between builds (recent example: the FDS
|
||||
* audio rewrite for #560 added/removed chunk tags, leaving older
|
||||
* savestates a fixed delta smaller than the new core's expected
|
||||
* size, with no recourse for the user). Accept any buffer at least
|
||||
* as large as the header; cap the upper end to a generous multiple
|
||||
* of the current size as a sanity guard against pathological input. */
|
||||
if (!data || size < 16 || size > retro_serialize_size() * 4)
|
||||
return false;
|
||||
|
||||
memstream_set_buffer((uint8_t*)data, size);
|
||||
|
||||
Reference in New Issue
Block a user