Closed Bug 1897013 Opened 4 months ago Closed 4 months ago

Assertion failure: color == MarkColor::Black, at /builds/worker/checkouts/gecko/js/src/gc/Marking.cpp:256

Categories

(Core :: JavaScript: GC, defect)

defect

Tracking

()

RESOLVED FIXED
128 Branch
Tracking Status
firefox-esr115 --- wontfix
firefox126 --- wontfix
firefox127 --- wontfix
firefox128 --- fixed

People

(Reporter: tsmith, Assigned: jonco)

References

(Blocks 1 open bug)

Details

(Keywords: assertion, pernosco)

Attachments

(1 file)

Found while fuzzing m-c 20240515-fd46f1fdb469 (--enable-debug --enable-fuzzing)

No test cases have been reliable enough to reduce so far. javascript.options.mem.gc_zeal.mode=11 was set.

A Pernosco session is available here: https://pernos.co/debug/VyRa2RpXs3zW4o0tzR0lxg/index.html

Assertion failure: color == MarkColor::Black, at /builds/worker/checkouts/gecko/js/src/gc/Marking.cpp:256

#0 0x7fe641e54c2e in ShouldMarkCrossCompartment /builds/worker/checkouts/gecko/js/src/gc/Marking.cpp:256:5
#1 0x7fe641e54c2e in ShouldTraceCrossCompartment(JSTracer*, JSObject*, js::gc::Cell*, char const*) /builds/worker/checkouts/gecko/js/src/gc/Marking.cpp:322:10
#2 0x7fe641e543e7 in ShouldTraceCrossCompartment /builds/worker/checkouts/gecko/js/src/gc/Marking.cpp:329:10
#3 0x7fe641e543e7 in void js::TraceManuallyBarrieredCrossCompartmentEdge<JS::Value>(JSTracer*, JSObject*, JS::Value*, char const*) /builds/worker/checkouts/gecko/js/src/gc/Marking.cpp:503:7
#4 0x7fe641a5b754 in TraceCrossCompartmentEdge<JS::Value> /builds/worker/checkouts/gecko/js/src/gc/Tracer.h:333:3
#5 0x7fe641a5b754 in traceEdgeToTarget /builds/worker/checkouts/gecko/js/src/proxy/Proxy.cpp:866:3
#6 0x7fe641a5b754 in js::ProxyObject::trace(JSTracer*, JSObject*) /builds/worker/checkouts/gecko/js/src/proxy/Proxy.cpp:905:3
#7 0x7fe641e8c97a in doTrace /builds/worker/workspace/obj-build/dist/include/js/Class.h:660:5
#8 0x7fe641e8c97a in CallTraceHook(JSTracer*, JSObject*) /builds/worker/checkouts/gecko/js/src/gc/Marking.cpp:1219:12
#9 0x7fe641e8b1b3 in bool js::GCMarker::processMarkStackTop<0u>(js::SliceBudget&) /builds/worker/checkouts/gecko/js/src/gc/Marking.cpp:1602:3
#10 0x7fe641e8a711 in bool js::GCMarker::markOneColor<0u, (js::gc::MarkColor)1>(js::SliceBudget&) /builds/worker/checkouts/gecko/js/src/gc/Marking.cpp:1329:10
#11 0x7fe641e651d4 in bool js::GCMarker::doMarking<0u>(js::SliceBudget&, js::gc::ShouldReportMarkTime) /builds/worker/checkouts/gecko/js/src/gc/Marking.cpp:1297:10
#12 0x7fe641e64ca7 in js::GCMarker::markUntilBudgetExhausted(js::SliceBudget&, js::gc::ShouldReportMarkTime) /builds/worker/checkouts/gecko/js/src/gc/Marking.cpp:1277:10
#13 0x7fe641e1bb6d in js::gc::GCRuntime::drainMarkStack() /builds/worker/checkouts/gecko/js/src/gc/GC.cpp:3142:3
#14 0x7fe641ef0c65 in markAllGrayReferences /builds/worker/checkouts/gecko/js/src/gc/Sweeping.cpp:591:3
#15 0x7fe641ef0c65 in js::gc::MarkingValidator::nonIncrementalMark(js::gc::AutoGCSession&) /builds/worker/checkouts/gecko/js/src/gc/Verifier.cpp:619:9
#16 0x7fe641edd1b1 in js::gc::GCRuntime::beginSweepPhase(JS::GCReason, js::gc::AutoGCSession&) /builds/worker/checkouts/gecko/js/src/gc/Sweeping.cpp:1744:3
#17 0x7fe641e1ed63 in js::gc::GCRuntime::incrementalSlice(js::SliceBudget&, JS::GCReason, bool) /builds/worker/checkouts/gecko/js/src/gc/GC.cpp:3810:7
#18 0x7fe641e22220 in js::gc::GCRuntime::gcCycle(bool, js::SliceBudget const&, JS::GCReason) /builds/worker/checkouts/gecko/js/src/gc/GC.cpp:4338:3
#19 0x7fe641e23953 in js::gc::GCRuntime::collect(bool, js::SliceBudget const&, JS::GCReason) /builds/worker/checkouts/gecko/js/src/gc/GC.cpp:4529:9
#20 0x7fe63bb15f6d in GarbageCollectImpl(JS::GCReason, nsJSContext::IsShrinking, js::SliceBudget const&) /builds/worker/checkouts/gecko/dom/base/nsJSEnvironment.cpp:1059:5
#21 0x7fe63bb161c0 in nsJSContext::RunIncrementalGCSlice(JS::GCReason, nsJSContext::IsShrinking, js::SliceBudget&) /builds/worker/checkouts/gecko/dom/base/nsJSEnvironment.cpp:1096:3
#22 0x7fe63b716643 in mozilla::CCGCScheduler::GCRunnerFiredDoGC(mozilla::TimeStamp, mozilla::GCRunnerStep const&) /builds/worker/checkouts/gecko/dom/base/CCGCScheduler.cpp:469:3
#23 0x7fe63b7159f4 in mozilla::CCGCScheduler::GCRunnerFired(mozilla::TimeStamp) /builds/worker/checkouts/gecko/dom/base/CCGCScheduler.cpp:428:10
#24 0x7fe639b73841 in operator() /builds/worker/fetches/sysroot-x86_64-linux-gnu/usr/lib/gcc/x86_64-linux-gnu/8/../../../../include/c++/8/bits/std_function.h:687:14
#25 0x7fe639b73841 in mozilla::IdleTaskRunner::Run() /builds/worker/checkouts/gecko/xpcom/threads/IdleTaskRunner.cpp:124:14
#26 0x7fe639b7440e in mozilla::IdleTaskRunnerTask::Run() /builds/worker/checkouts/gecko/xpcom/threads/IdleTaskRunner.cpp:45:15
#27 0x7fe639b83096 in mozilla::TaskController::DoExecuteNextTaskOnlyMainThreadInternal(mozilla::detail::BaseAutoLock<mozilla::Mutex&> const&) /builds/worker/checkouts/gecko/xpcom/threads/TaskController.cpp:907:26
#28 0x7fe639b819de in mozilla::TaskController::ExecuteNextTaskOnlyMainThreadInternal(mozilla::detail::BaseAutoLock<mozilla::Mutex&> const&) /builds/worker/checkouts/gecko/xpcom/threads/TaskController.cpp:772:15
#29 0x7fe639b81cf5 in mozilla::TaskController::ProcessPendingMTTask(bool) /builds/worker/checkouts/gecko/xpcom/threads/TaskController.cpp:516:36
#30 0x7fe639b919c6 in operator() /builds/worker/checkouts/gecko/xpcom/threads/TaskController.cpp:234:37
#31 0x7fe639b919c6 in mozilla::detail::RunnableFunction<mozilla::TaskController::TaskController()::$_0>::Run() /builds/worker/checkouts/gecko/xpcom/threads/nsThreadUtils.h:548:5
#32 0x7fe639ba6cf2 in nsThread::ProcessNextEvent(bool, bool*) /builds/worker/checkouts/gecko/xpcom/threads/nsThread.cpp:1199:16
#33 0x7fe639bade3d in NS_ProcessNextEvent(nsIThread*, bool) /builds/worker/checkouts/gecko/xpcom/threads/nsThreadUtils.cpp:480:10
#34 0x7fe63a8b7235 in mozilla::ipc::MessagePump::Run(base::MessagePump::Delegate*) /builds/worker/checkouts/gecko/ipc/glue/MessagePump.cpp:85:21
#35 0x7fe63a7cd0a1 in RunHandler /builds/worker/checkouts/gecko/ipc/chromium/src/base/message_loop.cc:363:3
#36 0x7fe63a7cd0a1 in MessageLoop::Run() /builds/worker/checkouts/gecko/ipc/chromium/src/base/message_loop.cc:345:3
#37 0x7fe63f284868 in nsBaseAppShell::Run() /builds/worker/checkouts/gecko/widget/nsBaseAppShell.cpp:148:27
#38 0x7fe63f346628 in nsAppShell::Run() /builds/worker/checkouts/gecko/widget/gtk/nsAppShell.cpp:469:33
#39 0x7fe6410655d4 in nsAppStartup::Run() /builds/worker/checkouts/gecko/toolkit/components/startup/nsAppStartup.cpp:296:30
#40 0x7fe6411d3990 in XREMain::XRE_mainRun() /builds/worker/checkouts/gecko/toolkit/xre/nsAppRunner.cpp:5770:22
#41 0x7fe6411d5040 in XREMain::XRE_main(int, char**, mozilla::BootstrapConfig const&) /builds/worker/checkouts/gecko/toolkit/xre/nsAppRunner.cpp:5982:8
#42 0x7fe6411d5cc2 in XRE_main(int, char**, mozilla::BootstrapConfig const&) /builds/worker/checkouts/gecko/toolkit/xre/nsAppRunner.cpp:6039:21
#43 0x5652518453a7 in do_main /builds/worker/checkouts/gecko/browser/app/nsBrowserApp.cpp:230:22
#44 0x5652518453a7 in main /builds/worker/checkouts/gecko/browser/app/nsBrowserApp.cpp:448:16
#45 0x7fe64eb27d8f in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16
#46 0x7fe64eb27e3f in __libc_start_main csu/../csu/libc-start.c:392:3
#47 0x56525181b1c8 in _start (/home/worker/builds/m-c-20240515032356-fuzzing-debug/firefox-bin+0x591c8) (BuildId: cd63beb80afcf153b4d505f337606914124f9b4d)
See Also: → 1743098

The source object here is an ObservableArrayProxyObject, and its target is not in fact cross-compartment. We always call TraceCrossCompartmentEdge in ProxyObject::traceEdgeToTarget regardless of whether the proxy is a CCW. This doesn't make any difference except we have more assertions on this path, one of which is failing here.

Depends on: 1897473

The problem here is we're not collecting the nursery during incremental marking validation. When we mark the heap we must always evict the nursery at the start. But when incremental marking validation re-marks the heap non-incrementally (to have something to compare against) we don't do this. This triggers the assertion failure. As noted above it's only picked up when tracing (possibly) cross compartment edges.

Marking (including that done by the incremental marking validator) requires
that we evcit the nursery first. This currently doesn't happen and the nursery
may be non-empty during an incremental GC.

This only affects use of the incremental marking validator which is not present
in release builds.

Assignee: nobody → jcoppeard
Status: NEW → ASSIGNED

Not security sensitive as this is a problem with marking validation and does not affect release builds.

Group: javascript-core-security
Pushed by jcoppeard@mozilla.com:
https://hg.mozilla.org/integration/autoland/rev/06f00f9d29c9
Collect the nursery at the start of GC slices if we might run the incremental marking validator r=sfink
Status: ASSIGNED → RESOLVED
Closed: 4 months ago
Resolution: --- → FIXED
Target Milestone: --- → 128 Branch
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: