Closed Bug 2031862 Opened 1 month ago Closed 1 day ago

crash at null in [@ mozilla::dom::Animation::AutoAlignStartTime]

Categories

(Core :: DOM: Animation, defect)

defect

Tracking

()

RESOLVED FIXED
152 Branch
Tracking Status
firefox-esr140 --- unaffected
firefox149 --- unaffected
firefox150 --- unaffected
firefox151 --- wontfix
firefox152 --- fixed

People

(Reporter: tsmith, Assigned: hiro)

References

(Blocks 2 open bugs, Regression)

Details

(4 keywords, Whiteboard: [bugmon:bisected,confirmed], [wptsync upstream])

Attachments

(2 files, 1 obsolete file)

Attached file testcase.html

Found while fuzzing m-c 20260406-264d49b61bdb (--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>
==70725==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000000 (pc 0x7bffd4e5b78e bp 0x7fffffff9fd0 sp 0x7fffffff9f40 T0)
==70725==The signal is caused by a READ memory access.
==70725==Hint: address points to the zero page.
    #0 0x7bffd4e5b78e in mozilla::dom::Animation::AutoAlignStartTime() /builds/worker/checkouts/gecko/dom/animation/Animation.cpp:2182:38
    #1 0x7bffd4e5b03f in mozilla::dom::Animation::Tick(mozilla::dom::AnimationTimeline::TickState&) /builds/worker/checkouts/gecko/dom/animation/Animation.cpp:1047:3
    #2 0x7bffd4e742cd in mozilla::dom::CSSAnimation::Tick(mozilla::dom::AnimationTimeline::TickState&) /builds/worker/checkouts/gecko/dom/animation/CSSAnimation.cpp:125:14
    #3 0x7bffd4e6dbbe in mozilla::dom::AnimationTimeline::Tick(mozilla::dom::AnimationTimeline::TickState&) /builds/worker/checkouts/gecko/dom/animation/AnimationTimeline.cpp:64:16
    #4 0x7bffd4e6fbaa in mozilla::dom::DocumentTimeline::WillRefresh() /builds/worker/checkouts/gecko/dom/animation/DocumentTimeline.cpp:197:17
    #5 0x7bffd4e6f040 in mozilla::dom::AnimationTimelinesController::WillRefresh() /builds/worker/checkouts/gecko/dom/animation/AnimationTimelinesController.cpp:25:9
    #6 0x7bffdca07cd4 in UpdateAndReduceAnimations /builds/worker/checkouts/gecko/layout/base/nsRefreshDriver.cpp:2046:35
    #7 0x7bffdca07cd4 in operator() /builds/worker/checkouts/gecko/layout/base/nsRefreshDriver.cpp:2463:25
    #8 0x7bffdca07cd4 in operator() /builds/worker/checkouts/gecko/layout/base/nsRefreshDriver.cpp:1311:7
    #9 0x7bffdca07cd4 in RunRenderingPhaseLegacy<(lambda at /builds/worker/checkouts/gecko/layout/base/nsRefreshDriver.cpp:1290:35)> /builds/worker/checkouts/gecko/layout/base/nsRefreshDriver.cpp:1283:3
    #10 0x7bffdca07cd4 in void nsRefreshDriver::RunRenderingPhase<nsRefreshDriver::Tick(mozilla::layers::BaseTransactionId<mozilla::VsyncIdType>, mozilla::TimeStamp, nsRefreshDriver::IsExtraTick)::$_8>(mozilla::RenderingPhase, nsRefreshDriver::Tick(mozilla::layers::BaseTransactionId<mozilla::VsyncIdType>, mozilla::TimeStamp, nsRefreshDriver::IsExtraTick)::$_8&&, bool (*)(mozilla::dom::Document const&)) /builds/worker/checkouts/gecko/layout/base/nsRefreshDriver.cpp:1290:3
    #11 0x7bffdc9fec4f in nsRefreshDriver::Tick(mozilla::layers::BaseTransactionId<mozilla::VsyncIdType>, mozilla::TimeStamp, nsRefreshDriver::IsExtraTick) /builds/worker/checkouts/gecko/layout/base/nsRefreshDriver.cpp:2444:3
    #12 0x7bffdca15826 in TickDriver /builds/worker/checkouts/gecko/layout/base/nsRefreshDriver.cpp:364:13
    #13 0x7bffdca15826 in mozilla::RefreshDriverTimer::TickRefreshDrivers(mozilla::layers::BaseTransactionId<mozilla::VsyncIdType>, mozilla::TimeStamp, nsTArray<RefPtr<nsRefreshDriver>>&) /builds/worker/checkouts/gecko/layout/base/nsRefreshDriver.cpp:342:7
    #14 0x7bffdca155ea in mozilla::RefreshDriverTimer::Tick(mozilla::layers::BaseTransactionId<mozilla::VsyncIdType>, mozilla::TimeStamp) /builds/worker/checkouts/gecko/layout/base/nsRefreshDriver.cpp:358:5
    #15 0x7bffdca15261 in mozilla::VsyncRefreshDriverTimer::RunRefreshDrivers(mozilla::layers::BaseTransactionId<mozilla::VsyncIdType>, mozilla::TimeStamp) /builds/worker/checkouts/gecko/layout/base/nsRefreshDriver.cpp:948:5
    #16 0x7bffdca14109 in mozilla::VsyncRefreshDriverTimer::TickRefreshDriver(mozilla::layers::BaseTransactionId<mozilla::VsyncIdType>, mozilla::TimeStamp) /builds/worker/checkouts/gecko/layout/base/nsRefreshDriver.cpp:858:5
    #17 0x7bffdca12c72 in mozilla::VsyncRefreshDriverTimer::NotifyVsyncOnMainThread(mozilla::VsyncEvent const&) /builds/worker/checkouts/gecko/layout/base/nsRefreshDriver.cpp:755:5
    #18 0x7bffdca122a8 in mozilla::VsyncRefreshDriverTimer::RefreshDriverVsyncObserver::NotifyVsyncTimerOnMainThread() /builds/worker/checkouts/gecko/layout/base/nsRefreshDriver.cpp:589:14
    #19 0x7bffdca11edc in mozilla::VsyncRefreshDriverTimer::RefreshDriverVsyncObserver::NotifyVsync(mozilla::VsyncEvent const&) /builds/worker/checkouts/gecko/layout/base/nsRefreshDriver.cpp:546:9
    #20 0x7bffdb23d1eb in mozilla::dom::VsyncMainChild::RecvNotify(mozilla::VsyncEvent const&, float const&) /builds/worker/checkouts/gecko/dom/ipc/VsyncMainChild.cpp:64:15
    #21 0x7bffdb6d6f31 in mozilla::dom::PVsyncChild::OnMessageReceived(IPC::Message const&) /builds/worker/workspace/obj-build/ipc/ipdl/PVsyncChild.cpp:229:78
    #22 0x7bffd25c4832 in mozilla::ipc::PBackgroundChild::OnMessageReceived(IPC::Message const&) /builds/worker/workspace/obj-build/ipc/ipdl/PBackgroundChild.cpp:4953:32
    #23 0x7bffd251ac35 in mozilla::ipc::MessageChannel::DispatchAsyncMessage(mozilla::ipc::ActorLifecycleProxy*, IPC::Message const&) /builds/worker/checkouts/gecko/ipc/glue/MessageChannel.cpp:1798:25
    #24 0x7bffd251712e in mozilla::ipc::MessageChannel::DispatchMessage(mozilla::ipc::ActorLifecycleProxy*, std::unique_ptr<IPC::Message, std::default_delete<IPC::Message>>) /builds/worker/checkouts/gecko/ipc/glue/MessageChannel.cpp:1724:9
    #25 0x7bffd2517f47 in mozilla::ipc::MessageChannel::RunMessage(mozilla::ipc::ActorLifecycleProxy*, mozilla::ipc::MessageChannel::MessageTask&) /builds/worker/checkouts/gecko/ipc/glue/MessageChannel.cpp:1513:3
    #26 0x7bffd2519463 in mozilla::ipc::MessageChannel::MessageTask::Run() /builds/worker/checkouts/gecko/ipc/glue/MessageChannel.cpp:1615:14
    #27 0x7bffd0e210da in mozilla::RunnableTask::Run() /builds/worker/checkouts/gecko/xpcom/threads/TaskController.cpp:719:16
    #28 0x7bffd0e162b1 in mozilla::TaskController::RunTask(mozilla::Task*) /builds/worker/checkouts/gecko/xpcom/threads/TaskController.cpp:210:19
    #29 0x7bffd0e1d5ad in mozilla::TaskController::DoExecuteNextTaskOnlyMainThreadInternal(mozilla::detail::BaseAutoLock<mozilla::Mutex&> const&) /builds/worker/checkouts/gecko/xpcom/threads/TaskController.cpp:1358:20
    #30 0x7bffd0e1b088 in mozilla::TaskController::ExecuteNextTaskOnlyMainThreadInternal(mozilla::detail::BaseAutoLock<mozilla::Mutex&> const&) /builds/worker/checkouts/gecko/xpcom/threads/TaskController.cpp:1181:15
    #31 0x7bffd0e1b6a6 in mozilla::TaskController::ProcessPendingMTTask(bool) /builds/worker/checkouts/gecko/xpcom/threads/TaskController.cpp:655:36
    #32 0x7bffd0e34571 in operator() /builds/worker/checkouts/gecko/xpcom/threads/TaskController.cpp:347:37
    #33 0x7bffd0e34571 in mozilla::detail::RunnableFunction<mozilla::TaskController::TaskController()::$_0>::Run() /builds/worker/checkouts/gecko/xpcom/threads/nsThreadUtils.h:547:5
    #34 0x7bffd0e57e9c in nsThread::ProcessNextEvent(bool, bool*) /builds/worker/checkouts/gecko/xpcom/threads/nsThread.cpp:1179:16
    #35 0x7bffd0e60fe9 in NS_ProcessNextEvent(nsIThread*, bool) /builds/worker/checkouts/gecko/xpcom/threads/nsThreadUtils.cpp:465:10
    #36 0x7bffd25244ce in mozilla::ipc::MessagePump::Run(base::MessagePump::Delegate*) /builds/worker/checkouts/gecko/ipc/glue/MessagePump.cpp:83:21
    #37 0x7bffd24025c4 in RunInternal /builds/worker/checkouts/gecko/ipc/chromium/src/base/message_loop.cc:371:10
    #38 0x7bffd24025c4 in RunHandler /builds/worker/checkouts/gecko/ipc/chromium/src/base/message_loop.cc:364:3
    #39 0x7bffd24025c4 in MessageLoop::Run() /builds/worker/checkouts/gecko/ipc/chromium/src/base/message_loop.cc:346:3
    #40 0x7bffdc23d206 in nsBaseAppShell::Run() /builds/worker/checkouts/gecko/widget/nsBaseAppShell.cpp:151:27
    #41 0x7bffdc4248bb in nsAppShell::Run() /builds/worker/checkouts/gecko/widget/gtk/nsAppShell.cpp:553:33
    #42 0x7bffde4f606d in XRE_RunAppShell() /builds/worker/checkouts/gecko/toolkit/xre/nsEmbedFunctions.cpp:652:20
    #43 0x7bffd24025c4 in RunInternal /builds/worker/checkouts/gecko/ipc/chromium/src/base/message_loop.cc:371:10
    #44 0x7bffd24025c4 in RunHandler /builds/worker/checkouts/gecko/ipc/chromium/src/base/message_loop.cc:364:3
    #45 0x7bffd24025c4 in MessageLoop::Run() /builds/worker/checkouts/gecko/ipc/chromium/src/base/message_loop.cc:346:3
    #46 0x7bffde4f4fbc in XRE_InitChildProcess(int, char**, XREChildData const*) /builds/worker/checkouts/gecko/toolkit/xre/nsEmbedFunctions.cpp:590:34
    #47 0x55555570885a in main /builds/worker/checkouts/gecko/browser/app/nsBrowserApp.cpp:467:22
Flags: in-testsuite?
Keywords: regression
Regressed by: 2020822

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

:boris, since you are the author of the regressor, bug 2020822, could you take a look? Also, could you set the severity field?

For more information, please visit BugBot documentation.

Flags: needinfo?(boris.chiou)

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

Start: e2c3a10ed4164bf8b2898c3ed6661edaaa8f477f (20260403204549)
End: f9fa398be2628e2541b8a61fba314958565e3261 (20260403234958)
Pushlog: https://hg.mozilla.org/integration/autoland/pushloghtml?fromchange=e2c3a10ed4164bf8b2898c3ed6661edaaa8f477f&tochange=f9fa398be2628e2541b8a61fba314958565e3261

Whiteboard: [bugmon:bisected,confirmed]

Looks like we hit this function for document timeline

Assignee: nobody → boris.chiou
Flags: needinfo?(boris.chiou)

The severity field is not set for this bug.
:boris, could you have a look please?

For more information, please visit BugBot documentation.

Flags: needinfo?(boris.chiou)
Severity: -- → S3
Flags: needinfo?(boris.chiou)

We take a bit of a shortcut when replacing animations, namely when it refers to the same keyframes, by replacing changed properties in that old animation.

Basically, scroll timeline animation gets created, the mAutoAlignStartTime is set during construction, then when we replace the timeline, we don't clear the flag, reaching this assert.

Assign to :hiro because of this patch: https://phabricator.services.mozilla.com/D300738

Assignee: boris.chiou → hikezoe.birchill

mAutoAlignStartTime is only meaningful for finite timelines: it is set in
the toFiniteTimeline branch of Animation::SetTimelineNoUpdate, and the
AutoAlignStartTime procedure asserts that the current timeline is not
monotonically increasing.

The other branch in SetTimelineNoUpdate only runs SetCurrentTimeNoUpdate
(which clears mAutoAlignStartTime as a side effect via SilentlySetCurrentTime)
when previous progress is resolved. For a pause-pending scroll-driven
animation whose start time was never auto-aligned -- mStartTime null,
mHoldTime null, so previousCurrentTime and previousProgress are both null --
that branch is skipped and the animation lands on the new (potentially
monotonic) timeline still carrying mAutoAlignStartTime = true.

Clear the flag unconditionally in the fromFiniteTimeline branch so the
invariant holds regardless of previousProgress, and keep the existing
SetCurrentTimeNoUpdate call nested inside the previous-progress check.

mAutoAlignStartTime is only meaningful for finite timelines: it is set in
the toFiniteTimeline branch of Animation::SetTimelineNoUpdate, and the
AutoAlignStartTime procedure asserts that the current timeline is not
monotonically increasing.

The other branch in SetTimelineNoUpdate only runs SetCurrentTimeNoUpdate
(which clears mAutoAlignStartTime as a side effect via SilentlySetCurrentTime)
when previous progress is resolved. For a pause-pending scroll-driven
animation whose start time was never auto-aligned -- mStartTime null,
mHoldTime null, so previousCurrentTime and previousProgress are both null --
that branch is skipped and the animation lands on the new (potentially
monotonic) timeline still carrying mAutoAlignStartTime = true.

Per spec [1], the fromFiniteTimeline branch only acts when previous
progress is resolved and says nothing about the unresolved case. We
deviate by unconditionally clearing mAutoAlignStartTime in that branch,
because otherwise the flag's invariant (only true while the timeline is
finite) is violated and AutoAlignStartTime would later fire on a
monotonic timeline.

Clear the flag unconditionally in the fromFiniteTimeline branch so the
invariant holds regardless of previousProgress, and keep the existing
SetCurrentTimeNoUpdate call nested inside the previous-progress check.

[1] https://drafts.csswg.org/web-animations-2/#setting-the-timeline

Blocks: 2039745
Attachment #9586964 - Attachment is obsolete: true
Pushed by hikezoe.birchill@mozilla.com: https://github.com/mozilla-firefox/firefox/commit/a8588405288d https://hg.mozilla.org/integration/autoland/rev/cf7a1644bfc0 Clear mAutoAlignStartTime when transitioning away from a finite timeline. r=layout-scroll-driven-animation-reviewers,boris
Status: NEW → RESOLVED
Closed: 1 day ago
Resolution: --- → FIXED
Target Milestone: --- → 152 Branch

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

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

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: