Closed Bug 2035793 Opened 19 days ago Closed 16 days ago

Assertion failure: bound(), at jit/shared/Assembler-shared.h:445 with Wasm stack switching

Categories

(Core :: JavaScript: WebAssembly, defect)

defect

Tracking

()

RESOLVED FIXED
152 Branch
Tracking Status
firefox152 --- fixed

People

(Reporter: jandem, Assigned: yury)

References

(Blocks 1 open bug)

Details

Attachments

(1 file)

Summary

An OOM during Ion code generation for the wasm resume instruction with
multiple handlers causes an assertion failure bound() in
CodeGenerator::visitWasmResume at Assembler-shared.h:445. The oomTest
harness triggers this reliably.

Root cause

In CodeGenerator::visitWasmResume (CodeGenerator.cpp:10580), the function
calls wasm::EmitResume(...) passing &resumeCodeOffset as an output
parameter (line 10621). If an OOM occurs inside EmitResume (e.g., during
MacroAssembler operations), the function doesn't actually emit code, and
resumeCodeOffset is left in its default unbound state.

However, immediately after EmitResume, line 10625 calls:

markSafepointAt(resumeCodeOffset.offset(), lir);

This calls resumeCodeOffset.offset() which asserts bound() — i.e., it
expects the CodeOffset to have been set by EmitResume. Under OOM, this
assertion fires, causing a crash (SEGV from MOZ_CrashSequence).

The function already has an OOM check for handlerLabels.reserve() at line
10611 (with a return), but there's no OOM check after EmitResume before
accessing its output parameter.

Possible fix

Add an OOM check after EmitResume:

wasm::EmitResume(masm, instance, cont, handlersParamsArea, ...
                 &resumeCodeOffset, &resumeFramePushed);

if (masm.oom()) {
    return;
}

markSafepointAt(resumeCodeOffset.offset(), lir);

Expected vs. observed

  • Expected: OOM is handled gracefully; compilation fails and returns an
    OOM error to JS.
  • Observed: Assertion failure: bound() at Assembler-shared.h:445,
    followed by SEGV.

Shell output

[1520] Assertion failure: bound(), at /firefox/js/src/jit/shared/Assembler-shared.h:445
    #0 MOZ_CrashSequence /firefox/obj-shell-dbgopt/dist/include/mozilla/Assertions.h:261
    #1 js::jit::CodeOffset::offset() /firefox/js/src/jit/shared/Assembler-shared.h:445
    #2 js::jit::CodeGenerator::visitWasmResume(LWasmResume*) CodeGenerator.cpp:10625
    #3 js::jit::CodeGenerator::generateBlock(...) CodeGenerator.cpp:8681
    ...

Test case (tested at git commit 410a52656dd13aa2360a3e96788e41bf48e80c0f):

// --fuzzing-safe -P wasm_stack_switching --wasm-compiler=ion
const bin = wasmTextToBinary(`(module
  (type $ft (func))
  (type $ct (cont $ft))
  (tag $tag1)
  (tag $tag2)
  (tag $tag3)
  (func $f (type $ft))
  (elem declare func $f)
  (func (export "run")
    (block (result (ref $ct))
      (block (result (ref $ct))
        (block (result (ref $ct))
          ref.func $f
          cont.new $ct
          resume $ct (on $tag1 0) (on $tag2 1) (on $tag3 2)
          unreachable
        )
        unreachable
      )
      unreachable
    )
    drop
  )
)`);
oomTest(function() {
  var m = new WebAssembly.Module(bin);
  return new WebAssembly.Instance(m, {});
});
Assignee: nobody → ydelendik
Status: NEW → ASSIGNED
Attachment #9575543 - Attachment description: Bug 2035793 - Add OOM checks after EmitResume/EmitSuspend before accessing unbound CodeOffset. r?#spidermonkey-reviewers → Bug 2035793 - Add OOM checks after EmitResume/EmitSuspend. r?rhunt
Status: ASSIGNED → RESOLVED
Closed: 16 days ago
Resolution: --- → FIXED
Target Milestone: --- → 152 Branch
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: