Closed Bug 957716 Opened 7 years ago Closed 7 years ago

ASan use-after-free [@ js::Binding::name()] with setObjectMetadataCallback


(Core :: JavaScript Engine, defect)

Not set





(Reporter: decoder, Unassigned)


(Keywords: csectype-uaf, testcase, Whiteboard: [asan])

The following testcase shows use-after-free on mozilla-central revision cf2d1bd796ea (run with --fuzzing-safe --ion-eager):

var lfcode = new Array();
eval = newGlobal('same-compartment').eval;
eval("setObjectMetadataCallback(function(obj) {});");
lfcode.push("eval('astring=new String(); astring.valueOf = String.prototype.valueOf; astring.valueOf();');");
lfcode.push("with (o) {}");
lfcode.push("function testcase() { try { testcase() >>>= 1; } catch (e) {} } testcase();");
while (true) {
	var file = lfcode.shift(); if (file == undefined) { break; }
function loadFile(lfVarx) {
    try {
        if (lfVarx.substr(-3) != ".js" && lfVarx.length != 1) {
            switch (lfRunTypeId) {
                default: function newFunc(x) { new Function(x)(); }; newFunc(lfVarx); break;
        } else if (!isNaN(lfVarx)) {
            lfRunTypeId = parseInt(lfVarx);
    } catch (lfVare) {}
Here's a condensed trace from ASan:

==23796==ERROR: AddressSanitizer: heap-use-after-free on address 0xf6102310 at pc 0x8ca305a bp 0xffacb0d8 sp 0xffacb0d0
READ of size 4 at 0xf6102310 thread T0
    #0 0x8ca3059 in js::Binding::name() const js/src/jsscript.h:160
    #1 0x8ca3059 in js::Bindings::trace(JSTracer*) js/src/jsscript.cpp:266
    #2 0x8ca3059 in JSScript::markChildren(JSTracer*) js/src/jsscript.cpp:2863
    #3 0x8317b76 in js::gc::MarkChildren(JSTracer*, JSScript*) js/src/gc/Marking.cpp:1042
    #4 0x8317b76 in js::TraceChildren(JSTracer*, void*, JSGCTraceKind) js/src/gc/Marking.cpp:1527
    #5 0x8327a72 in JS_TraceChildren(JSTracer*, void*, JSGCTraceKind) js/src/gc/Tracer.cpp:103
    #6 0x8327a72 in js::gc::StartVerifyPreBarriers(JSRuntime*) js/src/gc/Verifier.cpp:517
    #7 0x8afa95c in ~AutoStopVerifyingBarriers js/src/gc/GCInternals.h:143
    #8 0x8afa95c in ~AutoGCSlice js/src/gc/GCInternals.h:141
    #9 0x8afa95c in Collect(JSRuntime*, bool, long long, js::JSGCInvocationKind, JS::gcreason::Reason) js/src/jsgc.cpp:4945
    #10 0x8a9ede2 in js::GCSlice(JSRuntime*, js::JSGCInvocationKind, JS::gcreason::Reason, long long) js/src/jsgc.cpp:4969
    #11 0x8a9ede2 in js_InvokeOperationCallback(JSContext*) js/src/jscntxt.cpp:1017
    #12 0x8a9f01e in js_HandleExecutionInterrupt(JSContext*) js/src/jscntxt.cpp:1045
    #13 0x8e1152c in js::GetAndClearException(JSContext*, JS::MutableHandle<JS::Value>) js/src/vm/Interpreter.cpp:3695
    #14 0xf627509d (+0x1609d)
0xf6102310 is located 0 bytes inside of 8-byte region [0xf6102310,0xf6102318)
freed by thread T0 here:
    #0 0x81010f0 in free /srv/repos/llvm/projects/compiler-rt/lib/asan/
    #1 0x8c95d80 in js_free(void*) js/src/opt32asan/dist/include/js/Utility.h:167
    #2 0x8c95d80 in js::FreeOp::free_(void*) js/src/vm/Runtime.h:1903
    #3 0x8c95d80 in JSScript::finalize(js::FreeOp*) js/src/jsscript.cpp:2154
    #4 0x8aef281 in bool js::gc::Arena::finalize<JSScript>(js::FreeOp*, js::gc::AllocKind, unsigned int) js/src/jsgc.cpp:476
    #5 0x8aef281 in _ZL19FinalizeTypedArenasI8JSScriptEbPN2js6FreeOpEPPNS1_2gc11ArenaHeaderERNS4_9ArenaListENS4_9AllocKindERNS1_11SliceBudgetE js/src/jsgc.cpp:540
    #6 0x8aef281 in FinalizeArenas(js::FreeOp*, js::gc::ArenaHeader**, js::gc::ArenaList&, js::gc::AllocKind, js::SliceBudget&) js/src/jsgc.cpp:579
    #7 0x8b5ed38 in js::gc::ArenaLists::foregroundFinalize(js::FreeOp*, js::gc::AllocKind, js::SliceBudget&) js/src/jsgc.cpp:4054
    #8 0x8b5ed38 in SweepPhase(JSRuntime*, js::SliceBudget&) js/src/jsgc.cpp:4086
    #9 0x8b5ed38 in IncrementalCollectSlice(JSRuntime*, long long, JS::gcreason::Reason, js::JSGCInvocationKind) js/src/jsgc.cpp:4662
    #10 0x8b57c4f in GCCycle(JSRuntime*, bool, long long, js::JSGCInvocationKind, JS::gcreason::Reason) js/src/jsgc.cpp:4786
previously allocated by thread T0 here:
    #0 0x810132f in calloc /srv/repos/llvm/projects/compiler-rt/lib/asan/
    #1 0x8c89dec in js_calloc(unsigned int) js/src/opt32asan/dist/include/js/Utility.h:150
    #2 0x8c89dec in js::MallocProvider<js::ThreadSafeContext>::calloc_(unsigned int) js/src/vm/Runtime.h:618
    #3 0x8c89dec in AllocScriptData(js::ExclusiveContext*, unsigned int) js/src/jsscript.cpp:1856
    #4 0x8c89dec in JSScript::partiallyInit(js::ExclusiveContext*, JS::Handle<JSScript*>, unsigned int, unsigned int, unsigned int, unsigned int, unsigned int, unsigned int) js/src/jsscript.cpp:1872
SUMMARY: AddressSanitizer: heap-use-after-free js/src/jsscript.h:160 js::Binding::name() const
Shadow bytes around the buggy address:
=>0x3ec20460: fa fa[fd]fa fa fa fd fa fa fa fd fd fa fa fd fd
Shadow byte legend (one shadow byte represents 8 application bytes):
  Heap left redzone:     fa
  Freed heap region:     fd

Needinfo from jandem because bhackett is out.
Flags: needinfo?(jdemooij)
Keywords: csectype-uaf
Whiteboard: [asan]
deocder, I get a compartment mismatch on OS X 32-bit. Are you also seeing that or did you only try opt builds?
Flags: needinfo?(choller)
Indeed I didn't test with a debug build because ASan just runs on optimized builds. If this produces a compartment mismatch for you, it might be the same issue as bug 951632.
Flags: needinfo?(choller)
(In reply to Christian Holler (:decoder) from comment #3)
> If this produces a compartment mismatch for you, it might be the
> same issue as bug 951632.

OK, I posted a patch for that bug. We can verify this once that bug is fixed.
decoder, can you still reproduce this? Bug 951632 is on m-c now.
Flags: needinfo?(jdemooij) → needinfo?(choller)
Doesn't reproduce anymore, marking as duplicate.
Group: core-security
Closed: 7 years ago
Flags: needinfo?(choller)
Resolution: --- → DUPLICATE
Duplicate of bug: 951632
You need to log in before you can comment on or make changes to this bug.