Closed Bug 1474774 Opened 6 years ago Closed 3 years ago

Assertion failure: false (MOZ_ASSERT_UNREACHABLE: Attempted to subtract [n - nscoord_MAX]), at src/obj-firefox/dist/include/nsCoord.h:208

Categories

(Core :: Layout, defect, P3)

defect

Tracking

()

RESOLVED FIXED
90 Branch
Tracking Status
firefox-esr68 --- wontfix
firefox-esr78 --- wontfix
firefox63 --- wontfix
firefox69 --- wontfix
firefox70 --- wontfix
firefox71 --- wontfix
firefox88 --- wontfix
firefox89 --- wontfix
firefox90 --- fixed

People

(Reporter: tsmith, Assigned: MatsPalmgren_bugz)

References

(Blocks 1 open bug)

Details

(Keywords: assertion, testcase)

Attachments

(2 files)

Attached file testcase.html
Reduced with m-c:
BuildID=20180710230738
SourceStamp=3edc9c3ae818490ed36b8bfc8ffdfc9e222b41db

Assertion failure: false (MOZ_ASSERT_UNREACHABLE: Attempted to subtract [n - nscoord_MAX]), at src/obj-firefox/dist/include/nsCoord.h:208

#0 NSCoordSaturatingSubtract(int, int, int) src/obj-firefox/dist/include/nsCoord.h:222:14
#1 nsIFrame::InlinePrefISizeData::ForceBreak(mozilla::StyleClear) src/layout/generic/nsFrame.cpp:5440:5
#2 nsBlockFrame::GetPrefISize(gfxContext*) src/layout/generic/nsBlockFrame.cpp:886:8
#3 nsLayoutUtils::IntrinsicForAxis(mozilla::PhysicalAxis, gfxContext*, nsIFrame*, nsLayoutUtils::IntrinsicISizeType, mozilla::Maybe<mozilla::LogicalSize> const&, unsigned int, int) src/layout/base/nsLayoutUtils.cpp
#4 nsLayoutUtils::IntrinsicForContainer(gfxContext*, nsIFrame*, nsLayoutUtils::IntrinsicISizeType, unsigned int) src/layout/base/nsLayoutUtils.cpp:5498:10
#5 nsHTMLButtonControlFrame::GetPrefISize(gfxContext*) src/layout/forms/nsHTMLButtonControlFrame.cpp:169:14
#6 nsFrame::ShrinkWidthToFit(gfxContext*, int, nsIFrame::ComputeSizeFlags) src/layout/generic/nsFrame.cpp:6318:25
#7 nsContainerFrame::ComputeAutoSize(gfxContext*, mozilla::WritingMode, mozilla::LogicalSize const&, int, mozilla::LogicalSize const&, mozilla::LogicalSize const&, mozilla::LogicalSize const&, nsIFrame::ComputeSizeFlags) src/layout/generic/nsContainerFrame.cpp:862:27
#8 nsFrame::ComputeSize(gfxContext*, mozilla::WritingMode, mozilla::LogicalSize const&, int, mozilla::LogicalSize const&, mozilla::LogicalSize const&, mozilla::LogicalSize const&, nsIFrame::ComputeSizeFlags) src/layout/generic/nsFrame.cpp:5556:24
#9 mozilla::ReflowInput::InitConstraints(nsPresContext*, mozilla::LogicalSize const&, nsMargin const*, nsMargin const*, mozilla::LayoutFrameType) src/layout/generic/ReflowInput.cpp:2480:17
#10 mozilla::ReflowInput::Init(nsPresContext*, mozilla::LogicalSize const*, nsMargin const*, nsMargin const*) src/layout/generic/ReflowInput.cpp:414:3
#11 mozilla::ReflowInput::ReflowInput(nsPresContext*, mozilla::ReflowInput const&, nsIFrame*, mozilla::LogicalSize const&, mozilla::LogicalSize const*, unsigned int) src/layout/generic/ReflowInput.cpp:246:5
#12 void mozilla::Maybe<mozilla::ReflowInput>::emplace<nsPresContext*&, mozilla::ReflowInput const&, nsIFrame*&, mozilla::LogicalSize&>(nsPresContext*&, mozilla::ReflowInput const&, nsIFrame*&, mozilla::LogicalSize&) src/obj-firefox/dist/include/mozilla/Maybe.h:599:32
#13 nsLineLayout::ReflowFrame(nsIFrame*, nsReflowStatus&, mozilla::ReflowOutput*, bool&) src/layout/generic/nsLineLayout.cpp:862:23
#14 nsBlockFrame::ReflowInlineFrame(mozilla::BlockReflowInput&, nsLineLayout&, nsLineList_iterator, nsIFrame*, LineReflowStatus*) src/layout/generic/nsBlockFrame.cpp:4183:15
#15 nsBlockFrame::DoReflowInlineFrames(mozilla::BlockReflowInput&, nsLineLayout&, nsLineList_iterator, nsFlowAreaRect&, int&, nsFloatManager::SavedState*, bool*, LineReflowStatus*, bool) src/layout/generic/nsBlockFrame.cpp:3983:5
#16 nsBlockFrame::ReflowInlineFrames(mozilla::BlockReflowInput&, nsLineList_iterator, bool*) src/layout/generic/nsBlockFrame.cpp:3857:9
#17 nsBlockFrame::ReflowLine(mozilla::BlockReflowInput&, nsLineList_iterator, bool*) src/layout/generic/nsBlockFrame.cpp:2841:5
#18 nsBlockFrame::ReflowDirtyLines(mozilla::BlockReflowInput&) src/layout/generic/nsBlockFrame.cpp:2377:7
#19 nsBlockFrame::Reflow(nsPresContext*, mozilla::ReflowOutput&, mozilla::ReflowInput const&, nsReflowStatus&) src/layout/generic/nsBlockFrame.cpp:1239:3
#20 nsBlockReflowContext::ReflowBlock(mozilla::LogicalRect const&, bool, nsCollapsingMargin&, int, bool, nsLineBox*, mozilla::ReflowInput&, nsReflowStatus&, mozilla::BlockReflowInput&) src/layout/generic/nsBlockReflowContext.cpp:306:11
#21 nsBlockFrame::ReflowBlockFrame(mozilla::BlockReflowInput&, nsLineList_iterator, bool*) src/layout/generic/nsBlockFrame.cpp:3488:11
#22 nsBlockFrame::ReflowLine(mozilla::BlockReflowInput&, nsLineList_iterator, bool*) src/layout/generic/nsBlockFrame.cpp:2838:5
#23 nsBlockFrame::ReflowDirtyLines(mozilla::BlockReflowInput&) src/layout/generic/nsBlockFrame.cpp:2377:7
#24 nsBlockFrame::Reflow(nsPresContext*, mozilla::ReflowOutput&, mozilla::ReflowInput const&, nsReflowStatus&) src/layout/generic/nsBlockFrame.cpp:1239:3
#25 nsContainerFrame::ReflowChild(nsIFrame*, nsPresContext*, mozilla::ReflowOutput&, mozilla::ReflowInput const&, mozilla::WritingMode const&, mozilla::LogicalPoint const&, nsSize const&, unsigned int, nsReflowStatus&, nsOverflowContinuationTracker*) src/layout/generic/nsContainerFrame.cpp:951:14
#26 nsCanvasFrame::Reflow(nsPresContext*, mozilla::ReflowOutput&, mozilla::ReflowInput const&, nsReflowStatus&) src/layout/generic/nsCanvasFrame.cpp:769:5
#27 nsContainerFrame::ReflowChild(nsIFrame*, nsPresContext*, mozilla::ReflowOutput&, mozilla::ReflowInput const&, mozilla::WritingMode const&, mozilla::LogicalPoint const&, nsSize const&, unsigned int, nsReflowStatus&, nsOverflowContinuationTracker*) src/layout/generic/nsContainerFrame.cpp:951:14
#28 nsHTMLScrollFrame::ReflowScrolledFrame(mozilla::ScrollReflowInput*, bool, bool, mozilla::ReflowOutput*, bool) src/layout/generic/nsGfxScrollFrame.cpp:580:3
#29 nsHTMLScrollFrame::ReflowContents(mozilla::ScrollReflowInput*, mozilla::ReflowOutput const&) src/layout/generic/nsGfxScrollFrame.cpp:703:3
#30 nsHTMLScrollFrame::Reflow(nsPresContext*, mozilla::ReflowOutput&, mozilla::ReflowInput const&, nsReflowStatus&) src/layout/generic/nsGfxScrollFrame.cpp:1080:3
#31 nsContainerFrame::ReflowChild(nsIFrame*, nsPresContext*, mozilla::ReflowOutput&, mozilla::ReflowInput const&, int, int, unsigned int, nsReflowStatus&, nsOverflowContinuationTracker*) src/layout/generic/nsContainerFrame.cpp:995:14
#32 mozilla::ViewportFrame::Reflow(nsPresContext*, mozilla::ReflowOutput&, mozilla::ReflowInput const&, nsReflowStatus&) src/layout/generic/ViewportFrame.cpp:338:7
#33 mozilla::PresShell::DoReflow(nsIFrame*, bool) src/layout/base/PresShell.cpp:8994:11
#34 mozilla::PresShell::ProcessReflowCommands(bool) src/layout/base/PresShell.cpp:9167:24
#35 mozilla::PresShell::DoFlushPendingNotifications(mozilla::ChangesToFlush) src/layout/base/PresShell.cpp:4339:11
#36 nsRefreshDriver::Tick(long, mozilla::TimeStamp) src/layout/base/nsRefreshDriver.cpp:1960:16
#37 mozilla::RefreshDriverTimer::TickRefreshDrivers(long, mozilla::TimeStamp, nsTArray<RefPtr<nsRefreshDriver> >&) src/layout/base/nsRefreshDriver.cpp:303:7
#38 mozilla::RefreshDriverTimer::Tick(long, mozilla::TimeStamp) src/layout/base/nsRefreshDriver.cpp:322:5
#39 mozilla::VsyncRefreshDriverTimer::RunRefreshDrivers(mozilla::TimeStamp) src/layout/base/nsRefreshDriver.cpp:767:5
#40 mozilla::VsyncRefreshDriverTimer::RefreshDriverVsyncObserver::TickRefreshDriver(mozilla::TimeStamp) src/layout/base/nsRefreshDriver.cpp:679:16
#41 mozilla::VsyncRefreshDriverTimer::RefreshDriverVsyncObserver::NotifyVsync(mozilla::TimeStamp) src/layout/base/nsRefreshDriver.cpp:579:9
#42 mozilla::layout::VsyncChild::RecvNotify(mozilla::TimeStamp const&) src/layout/ipc/VsyncChild.cpp:68:16
#43 mozilla::layout::PVsyncChild::OnMessageReceived(IPC::Message const&) src/obj-firefox/ipc/ipdl/PVsyncChild.cpp:167:20
#44 mozilla::ipc::PBackgroundChild::OnMessageReceived(IPC::Message const&) src/obj-firefox/ipc/ipdl/PBackgroundChild.cpp:2181:28
#45 mozilla::ipc::MessageChannel::DispatchAsyncMessage(IPC::Message const&) src/ipc/glue/MessageChannel.cpp:2134:25
#46 mozilla::ipc::MessageChannel::DispatchMessage(IPC::Message&&) src/ipc/glue/MessageChannel.cpp:2064:17
#47 mozilla::ipc::MessageChannel::RunMessage(mozilla::ipc::MessageChannel::MessageTask&) src/ipc/glue/MessageChannel.cpp:1910:5
#48 mozilla::ipc::MessageChannel::MessageTask::Run() src/ipc/glue/MessageChannel.cpp:1943:15
#49 nsThread::ProcessNextEvent(bool, bool*) src/xpcom/threads/nsThread.cpp:1051:14
#50 NS_ProcessNextEvent(nsIThread*, bool) src/xpcom/threads/nsThreadUtils.cpp:519:10
#51 mozilla::ipc::MessagePump::Run(base::MessagePump::Delegate*) src/ipc/glue/MessagePump.cpp:97:21
#52 MessageLoop::RunInternal() src/ipc/chromium/src/base/message_loop.cc:325:10
#53 MessageLoop::Run() src/ipc/chromium/src/base/message_loop.cc:298:3
#54 nsBaseAppShell::Run() src/widget/nsBaseAppShell.cpp:158:27
#55 XRE_RunAppShell() src/toolkit/xre/nsEmbedFunctions.cpp:920:22
#56 mozilla::ipc::MessagePumpForChildProcess::Run(base::MessagePump::Delegate*) src/ipc/glue/MessagePump.cpp:269:9
#57 MessageLoop::RunInternal() src/ipc/chromium/src/base/message_loop.cc:325:10
#58 MessageLoop::Run() src/ipc/chromium/src/base/message_loop.cc:298:3
#59 XRE_InitChildProcess(int, char**, XREChildData const*) src/toolkit/xre/nsEmbedFunctions.cpp:746:34
#60 content_process_main(mozilla::Bootstrap*, int, char**) src/browser/app/../../ipc/contentproc/plugin-container.cpp:50:30
#61 main src/browser/app/nsBrowserApp.cpp:287:18
#62 __libc_start_main /build/glibc-Cl5G7W/glibc-2.23/csu/../csu/libc-start.c:291
#63 _start (firefox+0x423724)
Flags: in-testsuite?
Priority: -- → P3

InlinePrefISizeData::ForceBreak does:
NSCoordSaturatingSubtract(mCurrentLine, mTrailingWhitespace, nscoord_MAX);
mTrailingWhitespace is nscoord_MAX and came from:
https://searchfox.org/mozilla-central/rev/a8773ba2a8f015e0525f219a7e55087b04d30258/layout/generic/nsTextFrame.cpp#8476
(the testcase has word-spacing:15946245.3ch)

I tend to think we should simply remove this assertion...

Assignee: nobody → mats
Pushed by mpalmgren@mozilla.com:
https://hg.mozilla.org/integration/autoland/rev/bc593b46778c
Remove nscoord assertion that produce false positives.  r=dholbert
Created web-platform-tests PR https://github.com/web-platform-tests/wpt/pull/29083 for changes under testing/web-platform/tests

I'm a bit sad to lose this assertion, as it was capable of pointing out genuine issues - as it happens, it just showed up in bug 1710116, where it was the result of failure to appropriately use saturating addition earlier in the code. That resulted in values greater than nscoord_MAX, which isn't likely to end well... this assertion was the canary that let us know things were broken.

I disagree that bug 1710116 is a "genuine issue". It's a synthetic testcase using inline-size: 3579845520.820976vw which will never occur on any real web sites.

There are two ways to go about nscoord overflow that I think are reasonable:
A. Make nscoord a class type with overloaded arithmetic operators that systematically checks for overflow. I.e. make nscoord behave as a saturated integer type.
-or-
B. Don't try to prevent integer overflow anywhere, but add std::max(0, value) in a few strategic places where a positive value is expected, such as the result of calculating an intrinsic size or whatnot.

I firmly believe that B is the right choice. It just doesn't matter what the layout result is when nonsensical values like inline-size: 3579845520.820976vw are used. Take for example BasicTableLayoutStrategy::DistributeISizeToColumns - in this function we should simply remove all the NSCoordSaturatingAdd calls and then we can do a std::max(0, result) at the end (if we feel it's worth it). I just don't think that the performance penalty for doing A is worth it to handle these synthetic testcases.

And I don't think that sprinkling NSCoordSaturatingAdd calls in mostly random places is a reasonable solution.

Status: NEW → RESOLVED
Closed: 3 years ago
Resolution: --- → FIXED
Target Milestone: --- → 90 Branch
Flags: in-testsuite? → in-testsuite+
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: