Validate snapshot offsets before reading the compiled code (#5301) - #5311
Open
1820893135-pixel wants to merge 1 commit into
Open
1820893135-pixel wants to merge 1 commit into
1820893135-pixel wants to merge 1 commit into
Conversation
jerry_exec_snapshot() trusted the offsets stored in the snapshot header
and in the bytecode it deserializes:
* func_offsets[func_index] was used directly to locate the compiled
code, and its status_flags field was read without checking that the
offset was inside the snapshot;
* the size field of the compiled code header was used as the block
size, so a block could claim to extend beyond the input buffer and
the argument-header writes and literal loops below would touch
memory outside it;
* the literal offsets in the literal table were used the same way when
recursively loading a nested function.
A short malformed snapshot (73 bytes in the report) therefore made the
engine read and write outside the buffer:
==ERROR: AddressSanitizer: SEGV
#0 jerry_exec_snapshot jerry-snapshot.c:915
Check the fixed header size, the declared block size and the literal
offsets against the end of the snapshot before any of them is used, and
propagate the buffer bounds into snapshot_load_compiled_code() for the
recursive case. Malformed input now returns a normal exception instead
of dereferencing out-of-bounds memory.
Adds a regression case to tests/unit-core/test-snapshot.c.
JerryScript-DCO-1.0-Signed-off-by: 1820893135-pixel <1820893135@qq.com>
This was referenced Sep 23, 2026
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
jerry_exec_snapshot()deserializes an external buffer as a snapshot and truststhe offsets stored in it. Three of them bound the memory it touches, and none
were checked against the buffer size.
1. The function offset (
jerry-snapshot.c:915).func_offsets[func_index]is used to locate the compiled code, then
status_flagsis read from it:2. The declared block size.
snapshot_load_compiled_code()takesbytecode_p->sizeas the size of the block and everything below - theargument-header writes, the literal loops, the
code_sizebyte copy - assumesthe block lies inside the input.
3. The literal offsets. For
const_literal_end <= i < literal_end,literal_start_p[i]is used as an offset into the snapshot and recursed into.A 73-byte malformed snapshot walks off the buffer:
Fix
Check each offset against the end of the snapshot before it is used:
func_offsetand the literal offsets must leave at least the fixedecma_compiled_code_theader inside the buffer;snapshot_load_compiled_code()so therecursive literal load is checked the same way.
Well-formed snapshots are unaffected (the checks only reject blocks that claim
to extend past the input). Malformed input now returns a normal exception.
Testing
Adds a regression case to
tests/unit-core/test-snapshot.cusing the malformedsnapshot from the report. With the checks reverted the test aborts with the SEGV
above; with them it passes.
Fixes #5301.