Closed Bug 2014895 Opened 9 months ago Closed 9 months ago

AssertedCast error: Cannot cast 1.25829e+19 from double to int64_t: out of range [@ mozilla::FlacTrackDemuxer::TimeAtEnd]

Categories

(Core :: Audio/Video: Playback, defect, P2)

x86_64
Linux
defect

Tracking

()

VERIFIED FIXED
149 Branch
Tracking Status
firefox-esr115 --- wontfix
firefox-esr140 --- wontfix
firefox147 --- wontfix
firefox148 --- wontfix
firefox149 --- fixed

People

(Reporter: tsmith, Assigned: padenot)

References

(Regressed 1 open bug)

Details

(4 keywords, Whiteboard: [bugmon:bisected,confirmed][adv-main149-])

Crash Data

Attachments

(2 files, 1 external file)

Reproduced on mozilla-central rev ed1c0b4f0bbe (built with: --enable-debug --enable-fuzzing).

Testcase can be reproduced using the following commands:

$ pip install fuzzfetch grizzly-framework pipx --upgrade
$ python -m pipx ensurepath
$ fuzzfetch --build ed1c0b4f0bbe --debug --fuzzing  -n firefox
$ grizzly-replay-bugzilla ./firefox/firefox <bugid>
[@ MOZ_CrashSequence]

    ==47108==ERROR: UndefinedBehaviorSanitizer: SEGV on unknown address 0x000000000000 (pc 0x75e7d85e686c bp 0x75e7c123c840 sp 0x75e7c123c3f0 T47153)
    ==47108==The signal is caused by a WRITE memory access.
    ==47108==Hint: address points to the zero page.
        #0 0x75e7d85e686c in MOZ_CrashSequence /builds/worker/workspace/obj-build/dist/include/mozilla/Assertions.h:237:3
        #1 0x75e7d85e686c in AssertedCast<long, double> /builds/worker/workspace/obj-build/dist/include/mozilla/Casting.h:238:5
        #2 0x75e7d85e686c in mozilla::media::TimeUnit mozilla::media::TimeUnit::ToBase<mozilla::media::TimeUnit::TruncatePolicy>(long, double&) const /dom/media/TimeUnits.h:238:21
        #3 0x75e7d87b9b64 in mozilla::media::TimeUnit::operator-(mozilla::media::TimeUnit const&) const /dom/media/TimeUnits.cpp:316:28
        #4 0x75e7d88392a9 in mozilla::FlacTrackDemuxer::TimeAtEnd() /dom/media/flac/FlacDemuxer.cpp:1026:39
        #5 0x75e7d8836dfc in mozilla::FlacTrackDemuxer::Init() /dom/media/flac/FlacDemuxer.cpp:658:5
        #6 0x75e7d8836615 in mozilla::FlacDemuxer::InitInternal() /dom/media/flac/FlacDemuxer.cpp:567:25
        #7 0x75e7d8836eee in mozilla::FlacDemuxer::Init() /dom/media/flac/FlacDemuxer.cpp:571:8
        #8 0x75e7d8690611 in operator() /dom/media/MediaFormatReader.cpp:824:47
        #9 0x75e7d8690611 in mozilla::detail::ProxyFunctionRunnable<mozilla::MediaFormatReader::DemuxerProxy::Init()::$_2, mozilla::MozPromise<mozilla::MediaResult, mozilla::MediaResult, false>>::Run() /builds/worker/workspace/obj-build/dist/include/mozilla/MozPromise.h:1838:29
        #10 0x75e7d4341af0 in mozilla::TaskQueue::Runner::Run() /xpcom/threads/TaskQueue.cpp:311:20
        #11 0x75e7d436869e in nsThreadPool::Run() /xpcom/threads/nsThreadPool.cpp:446:14
        #12 0x75e7d435fec2 in nsThread::ProcessNextEvent(bool, bool*) /xpcom/threads/nsThread.cpp:1162:16
        #13 0x75e7d436594f in NS_ProcessNextEvent(nsIThread*, bool) /xpcom/threads/nsThreadUtils.cpp:461:10
        #14 0x75e7d4f56418 in mozilla::ipc::MessagePumpForNonMainThreads::Run(base::MessagePump::Delegate*) /ipc/glue/MessagePump.cpp:299:20
        #15 0x75e7d4eae691 in RunHandler /ipc/chromium/src/base/message_loop.cc:366:3
        #16 0x75e7d4eae691 in MessageLoop::Run() /ipc/chromium/src/base/message_loop.cc:348:3
        #17 0x75e7d435baee in nsThread::ThreadFunc(void*) /xpcom/threads/nsThread.cpp:373:10
        #18 0x75e7e5df83ac in _pt_root /nsprpub/pr/src/pthreads/ptthread.c:191:3
        #19 0x75e7e5a9caa3 in start_thread ./nptl/pthread_create.c:447:8
        #20 0x75e7e5b29c6b in clone3 ./misc/../sysdeps/unix/sysv/linux/x86_64/clone3.S:78:0
    
    ==47108==Register values:
    rax = 0x00000000000000ee  rbx = 0x000075e7c123c410  rcx = 0x00005f432a8ac118  rdx = 0x000075e7e5c04563
    rdi = 0x000075e7e5c05700  rsi = 0x0000000000000000  rbp = 0x000075e7c123c840  rsp = 0x000075e7c123c3f0
     r8 = 0x0000000000000000   r9 = 0x0000000000000003  r10 = 0x0000000000000002  r11 = 0x0000000000000293
    r12 = 0x00003b9aca000000  r13 = 0x0000000000000001  r14 = 0x0000000000000000  r15 = 0x000075e7c123c880
    UndefinedBehaviorSanitizer can not provide additional info.
    SUMMARY: UndefinedBehaviorSanitizer: SEGV (/home/user/workspace/browsers/m-c-20260205163736-fuzzing-debug/libxul.so+0x8be686c) (BuildId: 0b411186bb9521ab7e302998bc6191dc011c2d12)
    ==47108==ABORTING
Attached file Testcase —
Group: dom-core-security → media-core-security
Summary: Crash [@ MOZ_CrashSequence] → AssertedCast error: Cannot cast 1.25829e+19 from double to int64_t: out of range [@ mozilla::FlacTrackDemuxer::TimeAtEnd]

Verified bug as reproducible on mozilla-central 20260205213633-279b57ef4bf0.
Unable to bisect testcase (Testcase reproduces on start build!):

Start: ce0f77cae5a91e2cb4b1ec859117e08aa1182c52 (20250207164009)
End: ed1c0b4f0bbef7e458685d5f4743c73ae66cc3fd (20260205163736)
BuildFlags: BuildFlags(asan=False, tsan=False, debug=True, fuzzing=True, coverage=False, valgrind=False, no_opt=False, fuzzilli=False, nyx=False, searchfox=False, afl=False)

Whiteboard: [bugmon:confirm] → [bugmon:bisected,confirmed]
Blocks: media-triage

Running this in an ASan build does not trigger a failure.

Attached file (secure) —

When converting TimeUnits between vastly different bases with extreme tick
values, the conversion can produce a result that exceeds int64_t range,
causing an assertion failure in AssertedCast.

The issue manifests with malformed FLAC files where frames have inconsistent
sample rates. For example, a file with:

  • Initial frames: sample rate = 1, tick values in the billions
  • Final frames: sample rate = 192000 (normal audio rate)

When FlacTrackDemuxer::TimeAtEnd() calculates the track duration by
subtracting FirstFrame().Time() from the last frame's time, the TimeUnit
subtraction operator needs to convert both operands to a common base before
performing the arithmetic.

The conversion in ToBase() performs:
approx = (ticks * targetBase) / currentBase

With the extreme values above, this produces approximations that can exceed
INT64_MAX (~9.22e+18). In the fuzzer-discovered case, the approximation was
approximately 1.25829e+19.

Without bounds checking, the subsequent AssertedCast<int64_t>(rounded) would
assert in debug builds or cause undefined behavior in release builds.

The fix adds an explicit range check before the AssertedCast. If the rounded
value falls outside the valid int64_t range, we:

  1. Set aOutError to the fractional conversion error
  2. Return TimeUnit::Invalid()

This causes the TimeUnit::operator- to fall back to its "last resort" path
(lines 321-324), which converts both operands to floating-point seconds,
performs the subtraction, and converts back. While this loses some precision,
it handles extreme values gracefully without crashing.

This change only affects malformed media files with inconsistent frame timing.
Normal FLAC files with consistent sample rates are unaffected and continue
using the fast integer-based conversion path.

Assignee: nobody → padenot
Status: NEW → ASSIGNED
Severity: -- → S2
Priority: -- → P2

Something strange will happen (wrong duration displayed maybe?) but this is not a security issue. It's UB because we're essentially doing static_cast<int64_t>(1.25829e+19) (that doesn't fit), but having a wrong value here (regardless of the value) isn't dangerous.

sec-other

Keywords: sec-other
Pushed by padenot@mozilla.com: https://github.com/mozilla-firefox/firefox/commit/20aca1196fd1 https://hg.mozilla.org/integration/autoland/rev/18e99a7f5515 Handle int64_t overflow in TimeUnit::ToBase conversion. r=media-playback-reviewers,alwu
Pushed by sstanca@mozilla.com: https://github.com/mozilla-firefox/firefox/commit/6402666c71f0 https://hg.mozilla.org/integration/autoland/rev/43a70073b895 Revert "Bug 2014895 - Handle int64_t overflow in TimeUnit::ToBase conversion. r=media-playback-reviewers,alwu" for causing reftests failures in Assertions.h.
[task 2026-02-12T17:52:25.267+00:00] 17:52:25     INFO - REFTEST TEST-LOAD | file:///builds/worker/workspace/build/tests/reftest/tests/dom/media/test/crashtests/2014895.html | 847 / 4143 (20%)
[task 2026-02-12T17:52:25.298+00:00] 17:52:25     INFO - [3753] Assertion failure: mIsValid (Invalid checked integer (division by zero or integer overflow)), at /builds/worker/workspace/obj-build/dist/include/mozilla/CheckedInt.h:415
[task 2026-02-12T17:52:25.298+00:00] 17:52:25     INFO - #01: mozilla::media::TimeUnit::operator-(mozilla::media::TimeUnit const&) const [git:github.com/mozilla-firefox/firefox:dom/media/TimeUnits.cpp:20aca1196fd1681eb691414b4895e5ad6b3aae5a:307]
[task 2026-02-12T17:52:25.299+00:00] 17:52:25     INFO - #02: mozilla::media::TimeUnit::operator-(mozilla::media::TimeUnit const&) const [git:github.com/mozilla-firefox/firefox:dom/media/TimeUnits.cpp:20aca1196fd1681eb691414b4895e5ad6b3aae5a:318]
[task 2026-02-12T17:52:25.300+00:00] 17:52:25     INFO - #03: mozilla::FlacTrackDemuxer::TimeAtEnd() [git:github.com/mozilla-firefox/firefox:dom/media/flac/FlacDemuxer.cpp:20aca1196fd1681eb691414b4895e5ad6b3aae5a:1025]
[task 2026-02-12T17:52:25.300+00:00] 17:52:25     INFO - #04: mozilla::FlacTrackDemuxer::Init() [git:github.com/mozilla-firefox/firefox:dom/media/flac/FlacDemuxer.cpp:20aca1196fd1681eb691414b4895e5ad6b3aae5a:662]
[task 2026-02-12T17:52:25.301+00:00] 17:52:25     INFO - #05: mozilla::FlacDemuxer::InitInternal() [git:github.com/mozilla-firefox/firefox:dom/media/flac/FlacDemuxer.cpp:20aca1196fd1681eb691414b4895e5ad6b3aae5a:567]
[task 2026-02-12T17:52:25.301+00:00] 17:52:25     INFO - #06: mozilla::FlacDemuxer::Init() [git:github.com/mozilla-firefox/firefox:dom/media/flac/FlacDemuxer.cpp:20aca1196fd1681eb691414b4895e5ad6b3aae5a:0]
[task 2026-02-12T17:52:25.302+00:00] 17:52:25     INFO - #07: mozilla::detail::ProxyFunctionRunnable<mozilla::MediaFormatReader::DemuxerProxy::Init()::$_2, mozilla::MozPromise<mozilla::MediaResult, mozilla::MediaResult, false> >::Run() [git:github.com/mozilla-firefox/firefox:xpcom/threads/MozPromise.h:20aca1196fd1681eb691414b4895e5ad6b3aae5a:1838]
[task 2026-02-12T17:52:25.303+00:00] 17:52:25     INFO - #08: mozilla::TaskQueue::Runner::Run() [git:github.com/mozilla-firefox/firefox:xpcom/threads/TaskQueue.cpp:20aca1196fd1681eb691414b4895e5ad6b3aae5a:318]
[task 2026-02-12T17:52:25.303+00:00] 17:52:25     INFO - #09: nsThreadPool::Run() [git:github.com/mozilla-firefox/firefox:xpcom/threads/nsThreadPool.cpp:20aca1196fd1681eb691414b4895e5ad6b3aae5a:448]
[task 2026-02-12T17:52:25.304+00:00] 17:52:25     INFO - #10: nsThread::ProcessNextEvent(bool, bool*) [git:github.com/mozilla-firefox/firefox:xpcom/threads/nsThread.cpp:20aca1196fd1681eb691414b4895e5ad6b3aae5a:1163]
[task 2026-02-12T17:52:25.304+00:00] 17:52:25     INFO - #11: NS_ProcessNextEvent(nsIThread*, bool) [git:github.com/mozilla-firefox/firefox:xpcom/threads/nsThreadUtils.cpp:20aca1196fd1681eb691414b4895e5ad6b3aae5a:461]
[task 2026-02-12T17:52:25.305+00:00] 17:52:25     INFO - #12: mozilla::ipc::MessagePumpForNonMainThreads::Run(base::MessagePump::Delegate*) [git:github.com/mozilla-firefox/firefox:ipc/glue/MessagePump.cpp:20aca1196fd1681eb691414b4895e5ad6b3aae5a:300]
[task 2026-02-12T17:52:25.305+00:00] 17:52:25     INFO - #13: MessageLoop::Run() [git:github.com/mozilla-firefox/firefox:ipc/chromium/src/base/message_loop.cc:20aca1196fd1681eb691414b4895e5ad6b3aae5a:349]
[task 2026-02-12T17:52:25.306+00:00] 17:52:25     INFO - #14: nsThread::ThreadFunc(void*) [git:github.com/mozilla-firefox/firefox:xpcom/threads/nsThread.cpp:20aca1196fd1681eb691414b4895e5ad6b3aae5a:375]
[task 2026-02-12T17:52:25.309+00:00] 17:52:25     INFO - #15: _pt_root [git:github.com/mozilla-firefox/firefox:nsprpub/pr/src/pthreads/ptthread.c:20aca1196fd1681eb691414b4895e5ad6b3aae5a:194]
[task 2026-02-12T17:52:25.310+00:00] 17:52:25     INFO - #16: set_alt_signal_stack_and_start(PthreadCreateParams*) [git:github.com/mozilla-firefox/firefox:mozglue/interposers/pthread_create_interposer.cpp:20aca1196fd1681eb691414b4895e5ad6b3aae5a:81]
[task 2026-02-12T17:52:25.310+00:00] 17:52:25     INFO - #17: ??? [/lib/x86_64-linux-gnu/libc.so.6 + 0x9caa4]
[task 2026-02-12T17:52:25.311+00:00] 17:52:25     INFO - #18: __clone [/lib/x86_64-linux-gnu/libc.so.6 + 0x129a34]
[task 2026-02-12T17:52:25.311+00:00] 17:52:25     INFO - #19: ??? (???:???)
Flags: needinfo?(padenot)
Pushed by padenot@mozilla.com: https://github.com/mozilla-firefox/firefox/commit/6fe898185bf1 https://hg.mozilla.org/integration/autoland/rev/75bdf4b395ad Handle int64_t overflow in TimeUnit::ToBase conversion. r=media-playback-reviewers,alwu
Group: media-core-security → core-security-release
Status: ASSIGNED → RESOLVED
Closed: 9 months ago
Flags: needinfo?(padenot) → in-testsuite+
Resolution: --- → FIXED
Target Milestone: --- → 149 Branch

Verified bug as fixed on rev mozilla-central 20260213212122-0d74a4189e30.
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
No longer blocks: media-triage
Whiteboard: [bugmon:bisected,confirmed] → [bugmon:bisected,confirmed][adv-main149-]
Regressions: 2056822
Group: core-security-release
Keywords: keep-hidden
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: