Closed Bug 2036130 Opened 26 days ago Closed 5 days ago

crash near null in [@ nsINode::GetProperty]

Categories

(Core :: DOM: Animation, defect)

defect
Points:
1

Tracking

()

VERIFIED FIXED
153 Branch
Tracking Status
firefox-esr115 --- unaffected
firefox-esr140 --- unaffected
firefox150 --- unaffected
firefox151 --- unaffected
firefox152 + disabled
firefox153 --- verified

People

(Reporter: tsmith, Assigned: jwatt)

References

(Blocks 1 open bug, Regression)

Details

(5 keywords, Whiteboard: [scrollanimation:mvp][bugmon:bisected,confirmed], [wptsync upstream])

Crash Data

Attachments

(2 files)

Attached file testcase.html

Found while fuzzing m-c 20260428-499b89bd5492 (--enable-address-sanitizer --enable-fuzzing)

To reproduce via Grizzly Replay:

$ pip install fuzzfetch grizzly-framework --upgrade
$ python -m fuzzfetch -a --fuzzing -n firefox
$ python -m grizzly.replay.bugzilla ./firefox/firefox <bugid>
==87582==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000018 (pc 0x72391fd99c95 bp 0x7fff7c507c30 sp 0x7fff7c507c10 T0)
==87582==The signal is caused by a READ memory access.
==87582==Hint: address points to the zero page.
    #0 0x72391fd99c95 in HasFlag /builds/worker/checkouts/gecko/dom/base/nsWrapperCache.h:265:12
    #1 0x72391fd99c95 in HasProperties /builds/worker/checkouts/gecko/dom/base/nsINode.h:1152:39
    #2 0x72391fd99c95 in nsINode::GetProperty(nsAtom const*, nsresult*) const /builds/worker/workspace/obj-build/dom/base/./../../../../checkouts/gecko/dom/base/nsINode.cpp:304:8
    #3 0x7239274061a1 in mozilla::DisplayPortUtils::HasNonMinimalNonZeroDisplayPort(nsIContent*) /builds/worker/workspace/obj-build/layout/base/./../../../../checkouts/gecko/layout/base/DisplayPortUtils.cpp:475:17
    #4 0x72391f429415 in mozilla::dom::KeyframeEffect::IsMatchForCompositor(nsCSSPropertyIDSet const&, nsIFrame const*, mozilla::EffectSet const&, mozilla::AnimationPerformanceWarning::Type&) const /builds/worker/workspace/obj-build/dom/animation/./../../../../checkouts/gecko/dom/animation/KeyframeEffect.cpp:1990:16
    #5 0x72391f4413c6 in mozilla::dom::KeyframeEffect::GetPropertiesForCompositor(mozilla::EffectSet&, nsIFrame const*) const /builds/worker/workspace/obj-build/dom/animation/./../../../../checkouts/gecko/dom/animation/KeyframeEffect.cpp:378:9
    #6 0x723927539a21 in nsLayoutUtils::GetAnimationPropertiesForCompositor(nsIFrame const*) /builds/worker/workspace/obj-build/layout/base/./../../../../checkouts/gecko/layout/base/nsLayoutUtils.cpp:330:27
    #7 0x7239272c822e in operator() /builds/worker/workspace/obj-build/layout/style/./../../../../checkouts/gecko/layout/style/RestyleManager.cpp:1994:13
    #8 0x7239272c822e in operator() /builds/worker/workspace/obj-build/dist/include/mozilla/FunctionRef.h:179:35
    #9 0x7239272c822e in mozilla::FunctionRef<bool (mozilla::Maybe<unsigned long> const&, DisplayItemType)>::FunctionRef<mozilla::RestyleManager::AddLayerChangesForAnimation(nsIFrame*, nsIFrame*, mozilla::dom::Element*, nsChangeHint, nsStyleChangeList&)::$_0&, int, (void*)0>(mozilla::RestyleManager::AddLayerChangesForAnimation(nsIFrame*, nsIFrame*, mozilla::dom::Element*, nsChangeHint, nsStyleChangeList&)::$_0&)::'lambda'(mozilla::FunctionRef<bool (mozilla::Maybe<unsigned long> const&, DisplayItemType)>::Payload const&, mozilla::Maybe<unsigned long> const&, DisplayItemType)::__invoke(mozilla::FunctionRef<bool (mozilla::Maybe<unsigned long> const&, DisplayItemType)>::Payload const&, mozilla::Maybe<unsigned long> const&, DisplayItemType) /builds/worker/workspace/obj-build/dist/include/mozilla/FunctionRef.h:176:18
    #10 0x72391d93274e in operator() /builds/worker/workspace/obj-build/dist/include/mozilla/FunctionRef.h:209:12
    #11 0x72391d93274e in mozilla::layers::AnimationInfo::EnumerateGenerationOnFrame(nsIFrame const*, nsIContent const*, mozilla::Array<DisplayItemType, 3ul> const&, mozilla::FunctionRef<bool (mozilla::Maybe<unsigned long> const&, DisplayItemType)>) /builds/worker/workspace/obj-build/gfx/layers/./../../../../checkouts/gecko/gfx/layers/AnimationInfo.cpp:195:5
    #12 0x7239272a62f2 in mozilla::RestyleManager::AddLayerChangesForAnimation(nsIFrame*, nsIFrame*, mozilla::dom::Element*, nsChangeHint, nsStyleChangeList&) /builds/worker/workspace/obj-build/layout/style/./../../../../checkouts/gecko/layout/style/RestyleManager.cpp:2005:3
    #13 0x7239272a9701 in mozilla::RestyleManager::ProcessPostTraversal(mozilla::dom::Element*, mozilla::ServoRestyleState&, mozilla::ServoPostTraversalFlags) /builds/worker/workspace/obj-build/layout/style/./../../../../checkouts/gecko/layout/style/RestyleManager.cpp:2964:5
    #14 0x7239272ac2b1 in mozilla::RestyleManager::DoProcessPendingRestyles(mozilla::ServoTraversalFlags) /builds/worker/workspace/obj-build/layout/style/./../../../../checkouts/gecko/layout/style/RestyleManager.cpp:3200:28
    #15 0x7239272adb6e in mozilla::RestyleManager::ProcessPendingRestyles() /builds/worker/workspace/obj-build/layout/style/./../../../../checkouts/gecko/layout/style/RestyleManager.cpp:3318:3
    #16 0x723927448615 in mozilla::PresShell::DoFlushPendingNotifications(mozilla::ChangesToFlush) /builds/worker/workspace/obj-build/layout/base/./../../../../checkouts/gecko/layout/base/PresShell.cpp:4502:37
    #17 0x72391f93c5d2 in FlushPendingNotifications /builds/worker/workspace/obj-build/dist/include/mozilla/PresShell.h:1531:5
    #18 0x72391f93c5d2 in mozilla::dom::Document::FlushPendingNotifications(mozilla::ChangesToFlush) /builds/worker/workspace/obj-build/dom/base/./../../../../checkouts/gecko/dom/base/Document.cpp:11527:16
    #19 0x72391cfa147f in nsDocLoader::DocLoaderIsEmpty(bool, mozilla::Maybe<nsresult> const&) /builds/worker/workspace/obj-build/uriloader/base/./../../../../checkouts/gecko/uriloader/base/nsDocLoader.cpp:770:14
    #20 0x72391cfa4c63 in nsDocLoader::OnStopRequest(nsIRequest*, nsresult) /builds/worker/workspace/obj-build/uriloader/base/./../../../../checkouts/gecko/uriloader/base/nsDocLoader.cpp:703:5
    #21 0x723927e48f94 in nsDocShell::OnStopRequest(nsIRequest*, nsresult) /builds/worker/workspace/obj-build/docshell/base/./../../../../checkouts/gecko/docshell/base/nsDocShell.cpp:13057:23
    #22 0x72391b68efc1 in mozilla::net::nsLoadGroup::NotifyRemovalObservers(nsIRequest*, nsresult) /builds/worker/workspace/obj-build/netwerk/base/./../../../../checkouts/gecko/netwerk/base/nsLoadGroup.cpp:579:22
    #23 0x72391b691463 in mozilla::net::nsLoadGroup::RemoveRequest(nsIRequest*, nsISupports*, nsresult) /builds/worker/workspace/obj-build/netwerk/base/./../../../../checkouts/gecko/netwerk/base/nsLoadGroup.cpp:464:10
    #24 0x72391f8e3805 in DoUnblockOnload /builds/worker/workspace/obj-build/dom/base/./../../../../checkouts/gecko/dom/base/Document.cpp:12382:18
    #25 0x72391f8e3805 in mozilla::dom::Document::UnblockOnload(bool) /builds/worker/workspace/obj-build/dom/base/./../../../../checkouts/gecko/dom/base/Document.cpp:12321:7
    #26 0x72391f919804 in mozilla::dom::Document::DispatchContentLoadedEvents() /builds/worker/workspace/obj-build/dom/base/./../../../../checkouts/gecko/dom/base/Document.cpp:8583:3
    #27 0x72391fa5902f in operator()<> /builds/worker/workspace/obj-build/dist/include/nsThreadUtils.h:1070:18
    #28 0x72391fa5902f in __invoke_impl<void, (lambda at /builds/worker/workspace/obj-build/dist/include/nsThreadUtils.h:1069:9)> /builds/worker/fetches/sysroot-x86_64-linux-gnu/usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/invoke.h:60:14
    #29 0x72391fa5902f in __invoke<(lambda at /builds/worker/workspace/obj-build/dist/include/nsThreadUtils.h:1069:9)> /builds/worker/fetches/sysroot-x86_64-linux-gnu/usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/invoke.h:95:14
    #30 0x72391fa5902f in __apply_impl<(lambda at /builds/worker/workspace/obj-build/dist/include/nsThreadUtils.h:1069:9), std::tuple<> &> /builds/worker/fetches/sysroot-x86_64-linux-gnu/usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/tuple:1740:14
    #31 0x72391fa5902f in apply<(lambda at /builds/worker/workspace/obj-build/dist/include/nsThreadUtils.h:1069:9), std::tuple<> &> /builds/worker/fetches/sysroot-x86_64-linux-gnu/usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/tuple:1751:14
    #32 0x72391fa5902f in apply<mozilla::dom::Document, void (mozilla::dom::Document::*)()> /builds/worker/workspace/obj-build/dist/include/nsThreadUtils.h:1068:12
    #33 0x72391fa5902f in mozilla::detail::RunnableMethodImpl<mozilla::dom::Document*, void (mozilla::dom::Document::*)(), true, (mozilla::RunnableKind)0>::Run() /builds/worker/workspace/obj-build/dist/include/nsThreadUtils.h:1119:13
    #34 0x72391b26324a in mozilla::RunnableTask::Run() /builds/worker/workspace/obj-build/xpcom/threads/./../../../../checkouts/gecko/xpcom/threads/TaskController.cpp:719:16
    #35 0x72391b2580d9 in mozilla::TaskController::RunTask(mozilla::Task*) /builds/worker/workspace/obj-build/xpcom/threads/./../../../../checkouts/gecko/xpcom/threads/TaskController.cpp:210:19
    #36 0x72391b25f59d in mozilla::TaskController::DoExecuteNextTaskOnlyMainThreadInternal(mozilla::detail::BaseAutoLock<mozilla::Mutex&> const&) /builds/worker/workspace/obj-build/xpcom/threads/./../../../../checkouts/gecko/xpcom/threads/TaskController.cpp:1358:20
    #37 0x72391b25d078 in mozilla::TaskController::ExecuteNextTaskOnlyMainThreadInternal(mozilla::detail::BaseAutoLock<mozilla::Mutex&> const&) /builds/worker/workspace/obj-build/xpcom/threads/./../../../../checkouts/gecko/xpcom/threads/TaskController.cpp:1181:15
    #38 0x72391b25d696 in mozilla::TaskController::ProcessPendingMTTask(bool) /builds/worker/workspace/obj-build/xpcom/threads/./../../../../checkouts/gecko/xpcom/threads/TaskController.cpp:655:36
    #39 0x72391b276a61 in operator() /builds/worker/workspace/obj-build/xpcom/threads/./../../../../checkouts/gecko/xpcom/threads/TaskController.cpp:347:37
    #40 0x72391b276a61 in mozilla::detail::RunnableFunction<mozilla::TaskController::TaskController()::$_0>::Run() /builds/worker/checkouts/gecko/xpcom/threads/nsThreadUtils.h:536:5
    #41 0x72391b29b74c in nsThread::ProcessNextEvent(bool, bool*) /builds/worker/workspace/obj-build/xpcom/threads/./../../../../checkouts/gecko/xpcom/threads/nsThread.cpp:1179:16
    #42 0x72391b2a4b79 in NS_ProcessNextEvent(nsIThread*, bool) /builds/worker/workspace/obj-build/xpcom/threads/./../../../../checkouts/gecko/xpcom/threads/nsThreadUtils.cpp:472:10
    #43 0x72391ca5095e in mozilla::ipc::MessagePump::Run(base::MessagePump::Delegate*) /builds/worker/workspace/obj-build/ipc/glue/./../../../../checkouts/gecko/ipc/glue/MessagePump.cpp:83:21
    #44 0x72391c927e24 in RunInternal /builds/worker/workspace/obj-build/ipc/chromium/./../../../../checkouts/gecko/ipc/chromium/src/base/message_loop.cc:371:10
    #45 0x72391c927e24 in RunHandler /builds/worker/workspace/obj-build/ipc/chromium/./../../../../checkouts/gecko/ipc/chromium/src/base/message_loop.cc:364:3
    #46 0x72391c927e24 in MessageLoop::Run() /builds/worker/workspace/obj-build/ipc/chromium/./../../../../checkouts/gecko/ipc/chromium/src/base/message_loop.cc:346:3
    #47 0x723926bc6826 in nsBaseAppShell::Run() /builds/worker/workspace/obj-build/widget/./../../../checkouts/gecko/widget/nsBaseAppShell.cpp:151:27
    #48 0x723926dbd1eb in nsAppShell::Run() /builds/worker/workspace/obj-build/widget/gtk/./../../../../checkouts/gecko/widget/gtk/nsAppShell.cpp:553:33
    #49 0x723928f75b6d in XRE_RunAppShell() /builds/worker/checkouts/gecko/toolkit/xre/nsEmbedFunctions.cpp:652:20
    #50 0x72391c927e24 in RunInternal /builds/worker/workspace/obj-build/ipc/chromium/./../../../../checkouts/gecko/ipc/chromium/src/base/message_loop.cc:371:10
    #51 0x72391c927e24 in RunHandler /builds/worker/workspace/obj-build/ipc/chromium/./../../../../checkouts/gecko/ipc/chromium/src/base/message_loop.cc:364:3
    #52 0x72391c927e24 in MessageLoop::Run() /builds/worker/workspace/obj-build/ipc/chromium/./../../../../checkouts/gecko/ipc/chromium/src/base/message_loop.cc:346:3
    #53 0x723928f74a0c in XRE_InitChildProcess(int, char**, XREChildData const*) /builds/worker/checkouts/gecko/toolkit/xre/nsEmbedFunctions.cpp:590:34
    #54 0x625c9bf87c3a in main /builds/worker/checkouts/gecko/browser/app/nsBrowserApp.cpp:466:22
Flags: in-testsuite?
Crash Signature: [@ nsWrapperCache::HasFlag ]

Verified bug as reproducible on mozilla-central 20260430212929-d0c43f211001.
The bug appears to have been introduced in the following build range:

Start: 458a67bdb80257526376be228e652eb10902d136 (20260428074053)
End: 1b55fffadd0cfbc0825bcc71977af1841ec0548b (20260428083433)
Pushlog: https://hg.mozilla.org/integration/autoland/pushloghtml?fromchange=458a67bdb80257526376be228e652eb10902d136&tochange=1b55fffadd0cfbc0825bcc71977af1841ec0548b

Keywords: regression
Whiteboard: [bugmon:bisected,confirmed]

Claude's take:

What the patch did: It changed the condition in GetTimelineFromJS() from IsScrollTimeline() to
IsViewTimeline(). Before the patch, both ScrollTimeline and ViewTimeline were suppressed
(returned null from JS). After the patch, ScrollTimeline objects are now returned as a real timeline.

How that causes the crash: Once animation.timeline returns a valid ScrollTimeline, the compositor
path starts treating the animation as having a live scroll-driven timeline. The crash trace is:

KeyframeEffect::IsMatchForCompositor (line 1990)
  → DisplayPortUtils::HasNonMinimalNonZeroDisplayPort(nsIContent*)
    → nsINode::GetProperty
      → HasProperties / HasFlag   ← SEGV at 0x18

HasNonMinimalNonZeroDisplayPort is the scroll-container display port check, invoked when the compositor
decides whether a scroll-driven animation can be promoted. The nsIContent* it receives is the scroll
source element from the ScrollTimeline. That source can legitimately be null (the WebIDL source
attribute is Element?), but the code doesn't guard against it before dereferencing. Before this patch,
that code path was never reached because the timeline was suppressed; now it is.

Suggested fix:

The fix is in APZIsActiveForSource() at dom/animation/ScrollTimeline.cpp:248. Every other State method
that touches mSource.mElement either has a real null check (GetScrollContainerFrame at line 266) or
asserts + immediately dereferences. Only APZIsActiveForSource has the MOZ_ASSERT(e) without a real guard,
while GetScrollContainerFrame below it already shows the correct pattern.

The fix:
──────────────────────────────────────────────────────────────────────────
dom/animation/ScrollTimeline.cpp
──────────────────────────────────────────────────────────────────────────
247
248  bool ScrollTimeline::State::APZIsActiveForSource() const {
249    auto* e = mSource.mElement;
250 -  MOZ_ASSERT(e);
250 +  if (!e) {
251 +    return false;
252 +  }
253    return gfxPlatform::AsyncPanZoomEnabled() &&
254           !nsLayoutUtils::ShouldDisableApzForElement(e) &&
255           DisplayPortUtils::HasNonMinimalNonZeroDisplayPort(e);
──────────────────────────────────────────────────────────────────────────

The bug is marked as tracked for firefox152 (nightly). However, the bug still isn't assigned.

:fgriffith, could you please find an assignee for this tracked bug? Given that it is a regression and we know the cause, we could also simply backout the regressor. If you disagree with the tracking decision, please talk with the release managers.

For more information, please visit BugBot documentation.

Flags: needinfo?(fgriffith)
Assignee: nobody → mozmail
Flags: needinfo?(mozmail)
Whiteboard: [bugmon:bisected,confirmed] → [scrollanimation:triage][bugmon:bisected,confirmed]
Status: NEW → ASSIGNED
Points: --- → 1
Whiteboard: [scrollanimation:triage][bugmon:bisected,confirmed] → [scrollanimation:mvp][bugmon:bisected,confirmed]
Flags: needinfo?(fgriffith)

The bug is linked to a topcrash signature, which matches the following criterion:

  • Top 10 AArch64 and ARM crashes on nightly

For more information, please visit BugBot documentation.

Keywords: topcrash

The ScrollTimeline WebIDL constructor accepts a null source, so the
internal mSource.mElement can legitimately be null. Replace the
MOZ_ASSERT with an early return, matching the null check already in
the sibling GetScrollContainerFrame method below it.

Triaging as S3 given that this (specifically ScrollTimeline) is dependent on layout.css.scroll-driven-animations.enabled which is off-by-default in beta/release.

(This is flagged as a topcrash, but I think that's because the crash signature nsWrapperCache::HasFlag is pretty generic and probably includes a lot of crashes that have nothing to do with this pref or this testcase.)

Severity: -- → S3

Yeah, I mentioned the pref to RyanVM via DMs.

Good observation about the generic signature, thanks.

(In reply to Daniel Holbert [:dholbert] from comment #7)

(This is flagged as a topcrash, but I think that's because the crash signature nsWrapperCache::HasFlag is pretty generic and probably includes a lot of crashes that have nothing to do with this pref or this testcase.)

Correcting myself a bit -- I guess it was flagged as a topcrash on Nightly and most of the crash volume (skimming the first page of crash reports) does seem to be for Nightly. So maybe topcrash is accurate for this specific bug (for Nightly) after all.

Set release status flags based on info from the regressing bug 2016870

HI Jwatt, are you planning to update the patch and land it soon? This may block other implementation I think.

Flags: needinfo?(mozmail)

Thanks for publishing this.

Flags: needinfo?(mozmail)
Pushed by jwatt@jwatt.org: https://github.com/mozilla-firefox/firefox/commit/cdd5d0888c74 https://hg.mozilla.org/integration/autoland/rev/e1ecae85cc09 Avoid crash in APZIsActiveForSource when the ScrollTimeline source is null. r=boris
Status: ASSIGNED → RESOLVED
Closed: 5 days ago
Resolution: --- → FIXED
Target Milestone: --- → 153 Branch

Created web-platform-tests PR https://github.com/web-platform-tests/wpt/pull/60098 for changes under testing/web-platform/tests

Whiteboard: [scrollanimation:mvp][bugmon:bisected,confirmed] → [scrollanimation:mvp][bugmon:bisected,confirmed], [wptsync upstream]

Verified bug as fixed on rev mozilla-central 20260521211559-b754e06486cf.
Removing bugmon keyword as no further action possible. Please review the bug and re-add the keyword for further analysis.

Status: RESOLVED → VERIFIED
Keywords: bugmon

Upstream PR merged by moz-wptsync-bot

You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: