Closed Bug 1475943 Opened 4 years ago Closed 4 years ago

Assertion failure: isInt32(), at dist/include/js/Value.h:740 with wasm and gczeal

Categories

(Core :: JavaScript: WebAssembly, defect)

x86_64
Linux
defect
Not set
critical

Tracking

()

VERIFIED FIXED
mozilla63
Tracking Status
firefox-esr52 --- unaffected
firefox-esr60 --- unaffected
firefox61 --- unaffected
firefox62 --- unaffected
firefox63 --- verified

People

(Reporter: decoder, Assigned: bbouvier)

References

Details

(4 keywords, Whiteboard: [jsbugmon:update,bisect])

Attachments

(1 file)

The following testcase crashes on mozilla-central revision aff060ad3204 (build with --enable-posix-nspr-emulation --enable-valgrind --enable-gczeal --disable-tests --disable-profiling --enable-debug --enable-optimize, run with --fuzzing-safe --cpu-count=2):

var lfLogBuffer = `
Object.prototype[Symbol.split] = Object;
enableShellAllocationMetadataBuilder();
//corefuzz-dcd-endofdata
gczeal(9, 10);
function wasmEvalText(str, imports) {
    let binary = wasmTextToBinary(str);
    m = new WebAssembly.Module(binary);
    return new WebAssembly.Instance(m, imports);
}
wasmEvalText(\`(module
    (global (import "a" "b") i32)
    (export "g" (global 0))
    (func (export "get") (result i32) get_global 0))\`, { a: { b: 42 }}).exports.get() 
testInitExpr('i32', 13, 37, x => assertEq => {});
//corefuzz-dcd-endofdata
`;
lfLogBuffer = lfLogBuffer.split('\n');
function untemplate(s) {
  return s.replace(/\\/g, '\\\\')
}
var lfCodeBuffer = "";
while (true) {
    var line = lfLogBuffer.shift(); if (line == null) { break; }
    if (line == "//corefuzz-dcd-endofdata") {
        loadFile(lfCodeBuffer);
    } else {
        lfCodeBuffer += line + "\n";
    }
}
function loadFile(lfVarx) {
    evaluate(lfVarx);
    lfVarx = untemplate(lfVarx);
}


Backtrace:

received signal SIGSEGV, Segmentation fault.
#0  0x0000000000e524d0 in JS::Value::toInt32 (this=<optimized out>) at dist/include/js/Value.h:740
#1  js::WasmGlobalObject::type (this=this@entry=0x7ffff58980c0) at js/src/wasm/WasmJS.cpp:2421
#2  0x0000000000e52555 in js::WasmGlobalObject::trace (trc=0x7ffff5f1a688, obj=0x7ffff58980c0) at js/src/wasm/WasmJS.cpp:2158
#3  0x0000000000fc61eb in js::Class::doTrace (this=0x21172a0 <js::WasmGlobalObject::class_>, obj=0x7ffff58980c0, trc=0x7ffff5f1a688) at /srv/jenkins/jobs/mozilla-central-build-jsshell/workspace/arch/64/compiler/gcc/instrumentation/none/type/debug/dist/include/js/Class.h:893
#4  CallTraceHook<TraverseObjectFunctor, js::GCMarker*, JSObject*&> (check=CheckGeneration::DoChecks, obj=0x7ffff58980c0, trc=0x7ffff5f1a688, f=...) at js/src/gc/Marking.cpp:1499
#5  js::GCMarker::processMarkStackTop (this=this@entry=0x7ffff5f1a688, budget=...) at js/src/gc/Marking.cpp:1735
#6  0x0000000000fb2895 in js::GCMarker::drainMarkStack (this=this@entry=0x7ffff5f1a688, budget=...) at js/src/gc/Marking.cpp:1545
#7  0x0000000000f352db in js::gc::GCRuntime::drainMarkStack (this=this@entry=0x7ffff5f196d0, sliceBudget=..., phase=phase@entry=js::gcstats::PhaseKind::MARK) at js/src/gc/GC.cpp:5908
#8  0x0000000000f6504e in js::gc::GCRuntime::incrementalCollectSlice (this=this@entry=0x7ffff5f196d0, budget=..., reason=reason@entry=JS::gcreason::DEBUG_GC, session=...) at js/src/gc/GC.cpp:7116
#9  0x0000000000f6642e in js::gc::GCRuntime::gcCycle (this=this@entry=0x7ffff5f196d0, nonincrementalByAPI=nonincrementalByAPI@entry=false, budget=..., reason=reason@entry=JS::gcreason::DEBUG_GC) at js/src/gc/GC.cpp:7505
#10 0x0000000000f66c3d in js::gc::GCRuntime::collect (this=this@entry=0x7ffff5f196d0, nonincrementalByAPI=nonincrementalByAPI@entry=false, budget=..., reason=reason@entry=JS::gcreason::DEBUG_GC) at js/src/gc/GC.cpp:7679
#11 0x0000000000f6886b in js::gc::GCRuntime::runDebugGC (this=this@entry=0x7ffff5f196d0) at js/src/gc/GC.cpp:8258
#12 0x0000000000f689b3 in js::gc::GCRuntime::gcIfNeededAtAllocation (this=this@entry=0x7ffff5f196d0, cx=cx@entry=0x7ffff5f17000) at js/src/gc/Allocator.cpp:314
#13 0x0000000000f96dd8 in js::gc::GCRuntime::checkAllocatorState<(js::AllowGC)1> (this=this@entry=0x7ffff5f196d0, cx=cx@entry=0x7ffff5f17000, kind=kind@entry=js::gc::AllocKind::OBJECT0_BACKGROUND) at js/src/gc/Allocator.cpp:275
#14 0x0000000000f9701f in js::Allocate<JSObject, (js::AllowGC)1> (cx=cx@entry=0x7ffff5f17000, kind=<optimized out>, nDynamicSlots=nDynamicSlots@entry=0, heap=heap@entry=js::gc::DefaultHeap, clasp=clasp@entry=0x20e13c0 <js::PlainObject::class_>) at js/src/gc/Allocator.cpp:54
#15 0x0000000000ae0f4e in js::NativeObject::create (cx=0x7ffff5f17000, kind=<optimized out>, heap=js::gc::DefaultHeap, shape=..., group=...) at js/src/vm/NativeObject-inl.h:537
#16 0x0000000000c0a318 in NewObject (cx=0x7ffff5f17000, group=..., kind=<optimized out>, newKind=js::GenericObject, initialShapeFlags=<optimized out>) at js/src/vm/JSObject.cpp:751
#17 0x0000000000c0ac2d in js::NewObjectWithClassProtoCommon (cx=<optimized out>, cx@entry=0x7ffff5f17000, clasp=0x20e13c0 <js::PlainObject::class_>, protoArg=..., protoArg@entry=..., allocKind=js::gc::AllocKind::OBJECT0_BACKGROUND, newKind=newKind@entry=js::GenericObject) at js/src/vm/JSObject.cpp:872
#18 0x0000000000918f3b in js::NewObjectWithClassProto (newKind=js::GenericObject, allocKind=<optimized out>, proto=..., clasp=<optimized out>, cx=0x7ffff5f17000) at js/src/vm/JSObject-inl.h:679
#19 js::NewBuiltinClassInstance (newKind=js::GenericObject, allocKind=<optimized out>, clasp=<optimized out>, cx=0x7ffff5f17000) at js/src/vm/JSObject-inl.h:716
#20 js::NewBuiltinClassInstance (newKind=js::GenericObject, clasp=<optimized out>, cx=0x7ffff5f17000) at js/src/vm/JSObject-inl.h:723
#21 js::NewBuiltinClassInstance<js::PlainObject> (newKind=js::GenericObject, cx=0x7ffff5f17000) at js/src/vm/JSObject-inl.h:730
#22 ShellAllocationMetadataBuilder::build (this=<optimized out>, cx=<optimized out>, oomUnsafe=...) at js/src/builtin/TestingFunctions.cpp:2510
#23 0x0000000000c93f1b in JS::Realm::setNewObjectMetadata (this=0x7ffff5f3e800, cx=cx@entry=0x7ffff5f17000, obj=obj@entry=...) at js/src/vm/Realm.cpp:650
#24 0x0000000000ae14f0 in js::SetNewObjectMetadata<js::NativeObject> (obj=0x7ffff58980c0, cx=0x7ffff5f17000) at js/src/vm/JSObject-inl.h:382
#25 js::NativeObject::create (cx=0x7ffff5f17000, kind=<optimized out>, heap=<optimized out>, shape=..., group=...) at js/src/vm/NativeObject-inl.h:558
#26 0x0000000000c0a318 in NewObject (cx=0x7ffff5f17000, group=..., kind=<optimized out>, newKind=js::GenericObject, initialShapeFlags=<optimized out>) at js/src/vm/JSObject.cpp:751
#27 0x0000000000c0a792 in js::NewObjectWithGivenTaggedProto (cx=<optimized out>, cx@entry=0x7ffff5f17000, clasp=clasp@entry=0x21172a0 <js::WasmGlobalObject::class_>, proto=proto@entry=..., allocKind=js::gc::AllocKind::OBJECT4_BACKGROUND, newKind=newKind@entry=js::GenericObject, initialShapeFlags=initialShapeFlags@entry=0) at js/src/vm/JSObject.cpp:812
#28 0x0000000000e84bd1 in js::NewObjectWithGivenTaggedProto (initialShapeFlags=0, newKind=js::GenericObject, proto=..., clasp=0x21172a0 <js::WasmGlobalObject::class_>, cx=<optimized out>) at js/src/vm/JSObject-inl.h:603
#29 js::NewObjectWithGivenTaggedProto<js::WasmGlobalObject> (initialShapeFlags=0, newKind=js::GenericObject, proto=..., cx=<optimized out>) at js/src/vm/JSObject-inl.h:613
#30 js::NewObjectWithGivenProto<js::WasmGlobalObject> (newKind=js::GenericObject, proto=..., cx=<optimized out>) at js/src/vm/JSObject-inl.h:656
#31 js::WasmGlobalObject::create (cx=<optimized out>, cx@entry=0x7ffff5f17000, hval=hval@entry=..., isMutable=false) at js/src/wasm/WasmJS.cpp:2187
#32 0x0000000000e85c65 in EnsureGlobalObject (globalObjs=..., global=..., globalIndex=0, globalImportValues=..., cx=0x7ffff5f17000) at js/src/wasm/WasmModule.cpp:1051
#33 js::wasm::Module::instantiateGlobals (this=this@entry=0x7ffff543e130, cx=cx@entry=0x7ffff5f17000, globalImportValues=..., globalImportValues@entry=..., globalObjs=...) at js/src/wasm/WasmModule.cpp:1081
#34 0x0000000000e86159 in js::wasm::Module::instantiate (this=this@entry=0x7ffff543e130, cx=0x7ffff5f17000, funcImports=funcImports@entry=..., tableImport=..., tableImport@entry=..., memoryImport=..., memoryImport@entry=..., globalImportValues=..., globalImportValues@entry=..., globalObjs=..., instanceProto=..., instance=...) at js/src/wasm/WasmModule.cpp:1214
#35 0x0000000000e8811c in Instantiate (cx=<optimized out>, cx@entry=0x7ffff5f17000, module=..., importObj=..., importObj@entry=..., instanceObj=..., instanceObj@entry=...) at js/src/wasm/WasmJS.cpp:1203
#36 0x0000000000e88415 in js::WasmInstanceObject::construct (cx=0x7ffff5f17000, argc=<optimized out>, vp=<optimized out>) at js/src/wasm/WasmJS.cpp:1228
#37 0x00000000005bdd93 in CallJSNative (cx=0x7ffff5f17000, native=native@entry=0xe88260 <js::WasmInstanceObject::construct(JSContext*, unsigned int, JS::Value*)>, args=...) at js/src/vm/Interpreter.cpp:444
[...]
#46 0x0000000000a3eb0a in JS_ExecuteScript (cx=<optimized out>, envChain=..., scriptArg=..., scriptArg@entry=..., rval=..., rval@entry=...) at js/src/jsapi.cpp:4696
#47 0x00000000004714a3 in Evaluate (cx=<optimized out>, argc=<optimized out>, vp=<optimized out>) at js/src/shell/js.cpp:2033
#48 0x00000000005bdd93 in CallJSNative (cx=0x7ffff5f17000, native=0x470910 <Evaluate(JSContext*, unsigned int, JS::Value*)>, args=...) at js/src/vm/Interpreter.cpp:444
[...]
#56 0x00000000005b27aa in js::CallFromStack (cx=<optimized out>, args=...) at js/src/vm/Interpreter.cpp:589
#57 0x00000000006e9693 in js::jit::DoCallFallback (cx=<optimized out>, frame=0x7fffffffc728, stub_=<optimized out>, argc=<optimized out>, vp=0x7fffffffc6d8, res=...) at js/src/jit/BaselineIC.cpp:2657
#58 0x000010267d7eab7c in ?? ()
[...]
#80 0x0000000000000000 in ?? ()
rax	0x0	0
rbx	0x7ffff58980c0	140737312817344
rcx	0x7ffff6c282ad	140737333330605
rdx	0x0	0
rsi	0x7ffff6ef7770	140737336276848
rdi	0x7ffff6ef6540	140737336272192
rbp	0x7fffffff9110	140737488326928
rsp	0x7fffffff9110	140737488326928
r8	0x7ffff6ef7770	140737336276848
r9	0x7ffff7fe4780	140737354024832
r10	0x58	88
r11	0x7ffff6b9e7a0	140737332766624
r12	0x7ffff5f1a688	140737319642760
r13	0x7fffffff9190	140737488327056
r14	0x21172a0	34697888
r15	0x7ffff58980c0	140737312817344
rip	0xe524d0 <js::WasmGlobalObject::type() const+176>
=> 0xe524d0 <js::WasmGlobalObject::type() const+176>:	movl   $0x0,0x0
   0xe524db <js::WasmGlobalObject::type() const+187>:	ud2


Marking this s-s because the test involves gczeal and an assertion that can have security implications.
bbouvier: please help find a home for this bug if you're not the right person.
Flags: needinfo?(bbouvier)
Another regression from bug 1450261, taking.
Flags: needinfo?(bbouvier)
Attached patch fix.patchSplinter Review
What's happening is that a GC occurs just after we've allocated the GC object for the wasm Global, but before we've set its internal slots. This can happen because of the allocation metadata builder used in the test, which can allocate just after the actual object allocation (the information it creates is plain JS objects) thus cause a GC (yay for gczeal).

We've introduced a new function isNewborn() in the previous sec fuzz bug because of a similar case; basically when !isNewborn, the wasm global JSObject slots haven't been filled yet, which is what we want to test before tracing here (the wasm global's type is stored in a slot itself).

This is Nightly only, so no need for sec approval.
Assignee: nobody → bbouvier
Status: NEW → ASSIGNED
Attachment #8993441 - Flags: review?(jseward)
(as an aside, it would really help me track these bugs if they were set in the JavaScript Engine: Web Assembly component)
Component: JavaScript Engine → Javascript: Web Assembly
Attachment #8993441 - Flags: review?(jseward) → review+
Another trunk only issue, so landing.
https://hg.mozilla.org/mozilla-central/rev/5b31b8bf2d68
Group: javascript-core-security → core-security-release
Status: ASSIGNED → RESOLVED
Closed: 4 years ago
Resolution: --- → FIXED
Target Milestone: --- → mozilla63
Status: RESOLVED → VERIFIED
JSBugMon: This bug has been automatically verified fixed.
Group: core-security-release
You need to log in before you can comment on or make changes to this bug.