Assertion failure: framePtr->hasCachedSavedFrame() || hasGoodExcuse, at vm/SavedStacks.cpp:1483
Categories
(Core :: JavaScript Engine, defect, P3)
Tracking
()
People
(Reporter: sm-bugs, Assigned: jandem)
References
(Blocks 2 open bugs)
Details
(Keywords: csectype-dos, reporter-external, sec-low, Whiteboard: [adv-main128+])
Attachments
(4 files)
Steps to reproduce:
Checkout commit d9496bfef09039b2642da45585ca821c36917c6d and invoke the js shell as follows:
./js-spidermonkey-shell --fast-warmup --fuzzing-safe frameptr_has_cached_saved_frame.js
Actual results:
Assertion failure: framePtr->hasCachedSavedFrame() || hasGoodExcuse, at vm/SavedStacks.cpp:1483
Assignee | ||
Comment 1•11 months ago
|
||
More reduced test below. This has all the good stuff working together: Wasm <=> JS calls, promises, saved stacks, recover instruction throwing an exception during bailout. Still looking at it.
function f17(a18, a19) {
const v20 = a18 >> a18;
v20 <= v20 ? v20 : v20;
a19 ^ a19;
}
function f4() {
Promise.allSettled();
do {
f17(10n, -1n);
try {
f17(-2147483648n);
} catch {
}
} while (!inIon());
}
const binary = wasmTextToBinary(`
(module
(import "m" "f" (func $f))
(func (export "test")
(call $f)
)
)`);
const mod = new WebAssembly.Module(binary);
const inst = new WebAssembly.Instance(mod, {"m": {"f": f4}});
for (let i = 0; i < 5; i++) {
inst.exports.test();
}
Assignee | ||
Comment 2•11 months ago
|
||
Tthe JSJitFrameIter
constructor is always using the bailout data here but it should only do this for Exit
frames and not for JSJitToWasm
transition frames. The iterator could actually iloop in this case because iteration would start over again at the bailout frame. Oops.
It's certainly sketchy but I have to see what opt builds are doing to determine if this is security sensitive.
Assignee | ||
Comment 3•11 months ago
|
||
Updated•11 months ago
|
Updated•11 months ago
|
![]() |
||
Comment 5•11 months ago
|
||
Updated•11 months ago
|
Updated•11 months ago
|
Updated•11 months ago
|
This can still be triggered (on 97eeb1c55a5c73bd3938d4899685321a7967333b) using the following flags and the attached test case. However, it only crashes about 1 of 50 executions on my machine.
js --fuzzing-safe --fast-warmup --ion-check-range-analysis --ion-extra-checks --disable-oom-functions --enable-new-set-methods --small-function-length=1024 --inlining-entry-threshold=8 --gc-zeal=21,210 --ion-scalar-replacement=on --ion-pruning=on --ion-range-analysis=on --ion-inlining=on --ion-gvn=on --ion-osr=on --ion-edgecase-analysis=on --spectre-mitigations=on --ion-limit-script-size=on --ion-offthread-compile=on --ion-optimize-gcbarriers=on --ion-iterator-indices=on --nursery-size=2 --nursery-strings=on --nursery-bigints=on --enable-ic-frame-pointers --disable-bailout-loop-check --ion-optimize-shapeguards=on --ion-licm=on --ion-instruction-reordering=on --cache-ir-stubs=on --no-sse42 --monomorphic-inlining=default --ion-load-keys=off --ion-sink=off <testcase>
Assignee | ||
Comment 8•11 months ago
|
||
(In reply to Nils Bars from comment #6)
This can still be triggered (on 97eeb1c55a5c73bd3938d4899685321a7967333b) using the following flags and the attached test case. However, it only crashes about 1 of 50 executions on my machine.
Please file a new bug :) It's likely a different issue. This is a pretty generic assertion that has caught multiple different bugs over the years.
Comment 9•11 months ago
|
||
(In reply to Jan de Mooij [:jandem] from comment #2)
It's certainly sketchy but I have to see what opt builds are doing to determine if this is security sensitive.
You never fully replied what your assessment was. Can you add some extra details for the purpose of making a bug bounty decisions?
We did see you marked it as sec-low, but would like to hear a bit more if possible
Assignee | ||
Comment 10•11 months ago
|
||
(In reply to Frederik Braun [:freddy] from comment #9)
You never fully replied what your assessment was. Can you add some extra details for the purpose of making a bug bounty decisions?
We did see you marked it as sec-low, but would like to hear a bit more if possible
The frame iterator could get stuck in an infinite loop because it would restart at the first frame after we saw Wasm frames, instead of moving on to the next JS frame. In this case we use the frame iterator because we're creating a stack trace for an exception, and for that we cap the number of frames we iterate to MAX_REPORTED_STACK_DEPTH
(=128). I verified a non-debug build would just produce an incorrect stack trace (with about 128 frames).
Comment 11•11 months ago
|
||
Thanks! Looks like this doesn't meet the bar for a bug bounty then.
Updated•10 months ago
|
Updated•10 months ago
|
Updated•10 months ago
|
Updated•10 months ago
|
Comment 12•10 months ago
|
||
Updated•10 months ago
|
Updated•8 months ago
|
Updated•2 months ago
|
Description
•