jerryscript jerry-snapshot tool: unbounded literals-list parser -> global-buffer-overflow (OOB write) in process_generate
Severity: LOW | CVSS 3.1: 3.9 CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:N/I:L/A:L | CWE: CWE-787 | Affected: jerryscript @ b7069350c2e5
Summary
The jerry-snapshot command-line tool's --load-literals-list-format parser (process_generate) reads literal entries from a text file in a loop, incrementing num_of_lit and writing magic_string_items[num_of_lit] (an 8-byte pointer) and magic_string_lengths[num_of_lit] (a 4-byte attacker-controlled length) per entry, WITHOUT ever bounding num_of_lit against JERRY_LITERAL_LENGTH (4096), the size of those two fixed-size global arrays. A literals-list with more than 4096 positive-size entries writes past the end of magic_string_items (size 32768 = 4096*8) into adjacent globals (input_buffer), a controllable global-buffer-overflow write. This is in the jerry-snapshot tool, which is built only with -DJERRY_CMDLINE_SNAPSHOT=ON (documented, supported, but OFF by default; the default jerry binary does not contain it).
Affected
- Component: jerryscript@b7069350c2e52e7dc721dfb75f067147bd79b39b - jerry-main/main-snapshot.c:323 (process_generate, the --load-literals-list-format parser); fixed-size globals magic_string_items[4096]/magic_string_lengths[4096] declared at main-snapshot.c:47
- Repository / commit: https://github.com/jerryscript-project/jerryscript @
b7069350c2e52e7dc721dfb75f067147bd79b39b
- Attacker / interface: An actor who can supply the literals-list FILE consumed by
jerry-snapshot generate --load-literals-list-format <FILE> <src.js> (a local/build-time vector; the victim runs the snapshot generator on the attacker-provided list).
Root cause
jerry-main/main-snapshot.c:47 static const char *magic_string_items[JERRY_LITERAL_LENGTH]; static jerry_length_t magic_string_lengths[JERRY_LITERAL_LENGTH]; /* JERRY_LITERAL_LENGTH == 4096 */
... process_generate (~line 300-325): while parsing the literals-list, for each entry: magic_string_items[num_of_lit] = <ptr into input_buffer>; magic_string_lengths[num_of_lit] = <attacker length>; num_of_lit++; /* no `num_of_lit < JERRY_LITERAL_LENGTH` guard -> OOB write at entry #4097 (index 4096) */
Reachability (untrusted source -> sink)
- Build the snapshot tool: python3 tools/build.py --jerry-cmdline-snapshot=on (documented option; produces build/bin/jerry-snapshot). 2. jerry-snapshot generate --load-literals-list-format <src.js> -> process_generate parses -> unbounded loop -> OOB write. NOT reachable from the default
jerry binary (JERRY_CMDLINE_SNAPSHOT=OFF by default).
To reproduce
- git clone https://github.com/jerryscript-project/jerryscript && cd jerryscript && git checkout b706935
- python3 tools/build.py --jerry-cmdline-snapshot=on # documented option; builds build/bin/jerry-snapshot
- python3 -c "open('/tmp/lits.list','w').write('1 a\n'*4097)"
- printf 'var a=1;\n' > /tmp/src.js
- build/bin/jerry-snapshot generate --load-literals-list-format /tmp/lits.list /tmp/src.js -o /tmp/out.snapshot # -> OOB write past magic_string_items (crash; ASAN: global-buffer-overflow at main-snapshot.c:47)
-
Negative control (exactly 4096 entries): python3 -c "open('/tmp/lits.list','w').write('1 a\n'*4096)" then re-run -> clean snapshot, no overflow
Output
AddressSanitizer: global-buffer-overflow, WRITE of size 8, '0 bytes after global variable magic_string_items ... main-snapshot.c:47 of size 32768'. Deterministic across both runs, exact boundary at entry #4097.
Demonstrated vs inferred: Demonstrated: controllable global OOB write (8-byte pointer + 4-byte attacker value) past a fixed 4096-entry global array in the jerry-snapshot tool; crash/corruption. Not demonstrated: end-to-end exploitation. Severity reflects the local/non-default-build/file vector (Low).
Impact
Out-of-bounds write of a layout-controlled pointer plus a fully attacker-controlled 4-byte value past the magic_string_items global; demonstrated effect is memory corruption / crash of the jerry-snapshot generation tool. Low severity: requires the non-default jerry-snapshot build, a local literals-list file, and the victim to run the generator on it (developer/build-pipeline scenario), so real-world impact is limited.
Suggested fix
Bound the parse loop: reject or stop when num_of_lit reaches JERRY_LITERAL_LENGTH (e.g. if (num_of_lit >= JERRY_LITERAL_LENGTH) { error "too many literals"; } before writing magic_string_items[num_of_lit]/magic_string_lengths[num_of_lit]).
References
Environment
- jerryscript @ commit
b7069350c2e52e7dc721dfb75f067147bd79b39b - default build (./configure && make), default config.
jerryscript jerry-snapshot tool: unbounded literals-list parser -> global-buffer-overflow (OOB write) in process_generate
Severity: LOW | CVSS 3.1: 3.9
CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:N/I:L/A:L| CWE: CWE-787 | Affected: jerryscript @b7069350c2e5Summary
The jerry-snapshot command-line tool's
--load-literals-list-formatparser (process_generate) reads literal entries from a text file in a loop, incrementing num_of_lit and writing magic_string_items[num_of_lit] (an 8-byte pointer) and magic_string_lengths[num_of_lit] (a 4-byte attacker-controlled length) per entry, WITHOUT ever bounding num_of_lit against JERRY_LITERAL_LENGTH (4096), the size of those two fixed-size global arrays. A literals-list with more than 4096 positive-size entries writes past the end of magic_string_items (size 32768 = 4096*8) into adjacent globals (input_buffer), a controllable global-buffer-overflow write. This is in the jerry-snapshot tool, which is built only with -DJERRY_CMDLINE_SNAPSHOT=ON (documented, supported, but OFF by default; the defaultjerrybinary does not contain it).Affected
b7069350c2e52e7dc721dfb75f067147bd79b39bjerry-snapshot generate --load-literals-list-format <FILE> <src.js>(a local/build-time vector; the victim runs the snapshot generator on the attacker-provided list).Root cause
Reachability (untrusted source -> sink)
jerrybinary (JERRY_CMDLINE_SNAPSHOT=OFF by default).To reproduce
Negative control (exactly 4096 entries): python3 -c "open('/tmp/lits.list','w').write('1 a\n'*4096)" then re-run -> clean snapshot, no overflow
Output
AddressSanitizer: global-buffer-overflow, WRITE of size 8, '0 bytes after global variable magic_string_items ... main-snapshot.c:47 of size 32768'. Deterministic across both runs, exact boundary at entry #4097.
Demonstrated vs inferred: Demonstrated: controllable global OOB write (8-byte pointer + 4-byte attacker value) past a fixed 4096-entry global array in the jerry-snapshot tool; crash/corruption. Not demonstrated: end-to-end exploitation. Severity reflects the local/non-default-build/file vector (Low).
Impact
Out-of-bounds write of a layout-controlled pointer plus a fully attacker-controlled 4-byte value past the magic_string_items global; demonstrated effect is memory corruption / crash of the jerry-snapshot generation tool. Low severity: requires the non-default jerry-snapshot build, a local literals-list file, and the victim to run the generator on it (developer/build-pipeline scenario), so real-world impact is limited.
Suggested fix
Bound the parse loop: reject or stop when num_of_lit reaches JERRY_LITERAL_LENGTH (e.g.
if (num_of_lit >= JERRY_LITERAL_LENGTH) { error "too many literals"; }before writing magic_string_items[num_of_lit]/magic_string_lengths[num_of_lit]).References
Environment
b7069350c2e52e7dc721dfb75f067147bd79b39b- default build (./configure && make), default config.