Closed Bug 1209952 Opened 10 years ago Closed 7 years ago

Use-after-poison in nsFloatManager::GetFlowArea (with floats, multicol, and huge width)

Categories

(Core :: Layout, defect, P3)

44 Branch
defect

Tracking

()

RESOLVED FIXED
mozilla68
Tracking Status
firefox-esr52 --- wontfix
firefox-esr60 --- wontfix
firefox58 --- wontfix
firefox59 --- wontfix
firefox61 --- wontfix
firefox62 --- wontfix
firefox63 --- wontfix
firefox66 --- wontfix
firefox67 --- wontfix
firefox68 --- fixed

People

(Reporter: s.paraschoudis, Assigned: MatsPalmgren_bugz)

References

Details

(5 keywords, Whiteboard: [adv-main68-])

Crash Data

Attachments

(4 files, 1 obsolete file)

Attached file Crash test case
User Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_5) AppleWebKit/537.78.2 (KHTML, like Gecko) Version/6.1.6 Safari/537.78.2 Steps to reproduce: Am using asan-build from https://ftp.mozilla.org/pub/mozilla.org/firefox/tinderbox-builds/mozilla-central-linux64-asan/1443610148/ on Ubuntu 14.04 x64 Please note that this crashes latest firefox on OS X and Windows as well but feel free to remove the security restrictions since it's a use-after-poison. Actual results: Opening the test case yields: ==52781==ERROR: AddressSanitizer: use-after-poison on address 0x6250002a1118 at pc 0x7f2062625d2a bp 0x7fff94e3ab20 sp 0x7fff94e3ab18 READ of size 8 at 0x6250002a1118 thread T0 (Web Content) #0 0x7f2062625d29 in nsIFrame::StyleDisplay() const /builds/slave/m-cen-l64-asan-000000000000000/build/src/obj-firefox/dom/html/../../dist/include/nsStyleStructList.h:101 #1 0x7f20641c3196 in nsFloatManager::GetFlowArea(mozilla::WritingMode, int, nsFloatManager::BandInfoType, int, mozilla::LogicalRect, nsFloatManager::SavedState*, nsSize const&) const /builds/slave/m-cen-l64-asan-000000000000000/build/src/layout/generic/nsFloatManager.cpp:219 #2 0x7f206416fe91 in GetFloatAvailableSpaceWithState /builds/slave/m-cen-l64-asan-000000000000000/build/src/layout/generic/nsBlockReflowState.cpp:350 #3 0x7f206416fe91 in GetFloatAvailableSpace /builds/slave/m-cen-l64-asan-000000000000000/build/src/layout/generic/nsBlockReflowState.h:60 #4 0x7f206416fe91 in nsBlockReflowState::AddFloat(nsLineLayout*, nsIFrame*, int) /builds/slave/m-cen-l64-asan-000000000000000/build/src/layout/generic/nsBlockReflowState.cpp:633 #5 0x7f20640ea8f2 in GetOutermostLineLayout /builds/slave/m-cen-l64-asan-000000000000000/build/src/layout/generic/nsLineLayout.h:186 #6 0x7f20640ea8f2 in nsLineLayout::ReflowFrame(nsIFrame*, unsigned int&, nsHTMLReflowMetrics*, bool&) /builds/slave/m-cen-l64-asan-000000000000000/build/src/layout/generic/nsLineLayout.cpp:999 #7 0x7f2064154201 in nsBlockFrame::ReflowInlineFrame(nsBlockReflowState&, nsLineLayout&, nsLineList_iterator, nsIFrame*, LineReflowStatus*) /builds/slave/m-cen-l64-asan-000000000000000/build/src/layout/generic/nsBlockFrame.cpp:4035 #8 0x7f2064152a0d in nsBlockFrame::DoReflowInlineFrames(nsBlockReflowState&, nsLineLayout&, nsLineList_iterator, nsFlowAreaRect&, int&, nsFloatManager::SavedState*, bool*, LineReflowStatus*, bool) /builds/slave/m-cen-l64-asan-000000000000000/build/src/layout/generic/nsBlockFrame.cpp:3837 #9 0x7f20641491d2 in nsBlockFrame::ReflowInlineFrames(nsBlockReflowState&, nsLineList_iterator, bool*) /builds/slave/m-cen-l64-asan-000000000000000/build/src/layout/generic/nsBlockFrame.cpp:3703 #10 0x7f2064139591 in ReflowLine /builds/slave/m-cen-l64-asan-000000000000000/build/src/layout/generic/nsBlockFrame.cpp:2712 #11 0x7f2064139591 in nsBlockFrame::ReflowDirtyLines(nsBlockReflowState&) /builds/slave/m-cen-l64-asan-000000000000000/build/src/layout/generic/nsBlockFrame.cpp:2247 #12 0x7f2064131fc8 in nsBlockFrame::Reflow(nsPresContext*, nsHTMLReflowMetrics&, nsHTMLReflowState const&, unsigned int&) /builds/slave/m-cen-l64-asan-000000000000000/build/src/layout/generic/nsBlockFrame.cpp:1160 #13 0x7f206414fe47 in nsBlockReflowContext::ReflowBlock(mozilla::LogicalRect const&, bool, nsCollapsingMargin&, int, bool, nsLineBox*, nsHTMLReflowState&, unsigned int&, nsBlockReflowState&) /builds/slave/m-cen-l64-asan-000000000000000/build/src/layout/generic/nsBlockReflowContext.cpp:306 #14 0x7f2064145bad in nsBlockFrame::ReflowBlockFrame(nsBlockReflowState&, nsLineList_iterator, bool*) /builds/slave/m-cen-l64-asan-000000000000000/build/src/layout/generic/nsBlockFrame.cpp:3348 #15 0x7f20641395b3 in ReflowLine /builds/slave/m-cen-l64-asan-000000000000000/build/src/layout/generic/nsBlockFrame.cpp:2709 #16 0x7f20641395b3 in nsBlockFrame::ReflowDirtyLines(nsBlockReflowState&) /builds/slave/m-cen-l64-asan-000000000000000/build/src/layout/generic/nsBlockFrame.cpp:2247 #17 0x7f2064131fc8 in nsBlockFrame::Reflow(nsPresContext*, nsHTMLReflowMetrics&, nsHTMLReflowState const&, unsigned int&) /builds/slave/m-cen-l64-asan-000000000000000/build/src/layout/generic/nsBlockFrame.cpp:1160 #18 0x7f206419e1d1 in nsContainerFrame::ReflowChild(nsIFrame*, nsPresContext*, nsHTMLReflowMetrics&, nsHTMLReflowState const&, mozilla::WritingMode const&, mozilla::LogicalPoint const&, nsSize const&, unsigned int, unsigned int&, nsOverflowContinuationTracker*) /builds/slave/m-cen-l64-asan-000000000000000/build/src/layout/generic/nsContainerFrame.cpp:998 #19 0x7f2064188514 in nsColumnSetFrame::ReflowChildren(nsHTMLReflowMetrics&, nsHTMLReflowState const&, unsigned int&, nsColumnSetFrame::ReflowConfig const&, bool, nsCollapsingMargin*, nsColumnSetFrame::ColumnBalanceData&) /builds/slave/m-cen-l64-asan-000000000000000/build/src/layout/generic/nsColumnSetFrame.cpp:638 #20 0x7f206418c4bb in ReflowColumns /builds/slave/m-cen-l64-asan-000000000000000/build/src/layout/generic/nsColumnSetFrame.cpp:344 #21 0x7f206418c4bb in nsColumnSetFrame::Reflow(nsPresContext*, nsHTMLReflowMetrics&, nsHTMLReflowState const&, unsigned int&) /builds/slave/m-cen-l64-asan-000000000000000/build/src/layout/generic/nsColumnSetFrame.cpp:1075 #22 0x7f206414fe47 in nsBlockReflowContext::ReflowBlock(mozilla::LogicalRect const&, bool, nsCollapsingMargin&, int, bool, nsLineBox*, nsHTMLReflowState&, unsigned int&, nsBlockReflowState&) /builds/slave/m-cen-l64-asan-000000000000000/build/src/layout/generic/nsBlockReflowContext.cpp:306 #23 0x7f2064145bad in nsBlockFrame::ReflowBlockFrame(nsBlockReflowState&, nsLineList_iterator, bool*) /builds/slave/m-cen-l64-asan-000000000000000/build/src/layout/generic/nsBlockFrame.cpp:3348 #24 0x7f20641395b3 in ReflowLine /builds/slave/m-cen-l64-asan-000000000000000/build/src/layout/generic/nsBlockFrame.cpp:2709 #25 0x7f20641395b3 in nsBlockFrame::ReflowDirtyLines(nsBlockReflowState&) /builds/slave/m-cen-l64-asan-000000000000000/build/src/layout/generic/nsBlockFrame.cpp:2247 #26 0x7f2064131fc8 in nsBlockFrame::Reflow(nsPresContext*, nsHTMLReflowMetrics&, nsHTMLReflowState const&, unsigned int&) /builds/slave/m-cen-l64-asan-000000000000000/build/src/layout/generic/nsBlockFrame.cpp:1160 #27 0x7f206419e1d1 in nsContainerFrame::ReflowChild(nsIFrame*, nsPresContext*, nsHTMLReflowMetrics&, nsHTMLReflowState const&, mozilla::WritingMode const&, mozilla::LogicalPoint const&, nsSize const&, unsigned int, unsigned int&, nsOverflowContinuationTracker*) /builds/slave/m-cen-l64-asan-000000000000000/build/src/layout/generic/nsContainerFrame.cpp:998 #28 0x7f2064188514 in nsColumnSetFrame::ReflowChildren(nsHTMLReflowMetrics&, nsHTMLReflowState const&, unsigned int&, nsColumnSetFrame::ReflowConfig const&, bool, nsCollapsingMargin*, nsColumnSetFrame::ColumnBalanceData&) /builds/slave/m-cen-l64-asan-000000000000000/build/src/layout/generic/nsColumnSetFrame.cpp:638 #29 0x7f206418c4bb in ReflowColumns /builds/slave/m-cen-l64-asan-000000000000000/build/src/layout/generic/nsColumnSetFrame.cpp:344 #30 0x7f206418c4bb in nsColumnSetFrame::Reflow(nsPresContext*, nsHTMLReflowMetrics&, nsHTMLReflowState const&, unsigned int&) /builds/slave/m-cen-l64-asan-000000000000000/build/src/layout/generic/nsColumnSetFrame.cpp:1075 #31 0x7f206414fe47 in nsBlockReflowContext::ReflowBlock(mozilla::LogicalRect const&, bool, nsCollapsingMargin&, int, bool, nsLineBox*, nsHTMLReflowState&, unsigned int&, nsBlockReflowState&) /builds/slave/m-cen-l64-asan-000000000000000/build/src/layout/generic/nsBlockReflowContext.cpp:306 #32 0x7f2064145bad in nsBlockFrame::ReflowBlockFrame(nsBlockReflowState&, nsLineList_iterator, bool*) /builds/slave/m-cen-l64-asan-000000000000000/build/src/layout/generic/nsBlockFrame.cpp:3348 #33 0x7f20641395b3 in ReflowLine /builds/slave/m-cen-l64-asan-000000000000000/build/src/layout/generic/nsBlockFrame.cpp:2709 #34 0x7f20641395b3 in nsBlockFrame::ReflowDirtyLines(nsBlockReflowState&) /builds/slave/m-cen-l64-asan-000000000000000/build/src/layout/generic/nsBlockFrame.cpp:2247 #35 0x7f2064131fc8 in nsBlockFrame::Reflow(nsPresContext*, nsHTMLReflowMetrics&, nsHTMLReflowState const&, unsigned int&) /builds/slave/m-cen-l64-asan-000000000000000/build/src/layout/generic/nsBlockFrame.cpp:1160 #36 0x7f206414fe47 in nsBlockReflowContext::ReflowBlock(mozilla::LogicalRect const&, bool, nsCollapsingMargin&, int, bool, nsLineBox*, nsHTMLReflowState&, unsigned int&, nsBlockReflowState&) /builds/slave/m-cen-l64-asan-000000000000000/build/src/layout/generic/nsBlockReflowContext.cpp:306 #37 0x7f2064145bad in nsBlockFrame::ReflowBlockFrame(nsBlockReflowState&, nsLineList_iterator, bool*) /builds/slave/m-cen-l64-asan-000000000000000/build/src/layout/generic/nsBlockFrame.cpp:3348 #38 0x7f20641395b3 in ReflowLine /builds/slave/m-cen-l64-asan-000000000000000/build/src/layout/generic/nsBlockFrame.cpp:2709 #39 0x7f20641395b3 in nsBlockFrame::ReflowDirtyLines(nsBlockReflowState&) /builds/slave/m-cen-l64-asan-000000000000000/build/src/layout/generic/nsBlockFrame.cpp:2247 #40 0x7f2064131fc8 in nsBlockFrame::Reflow(nsPresContext*, nsHTMLReflowMetrics&, nsHTMLReflowState const&, unsigned int&) /builds/slave/m-cen-l64-asan-000000000000000/build/src/layout/generic/nsBlockFrame.cpp:1160 #41 0x7f206419e1d1 in nsContainerFrame::ReflowChild(nsIFrame*, nsPresContext*, nsHTMLReflowMetrics&, nsHTMLReflowState const&, mozilla::WritingMode const&, mozilla::LogicalPoint const&, nsSize const&, unsigned int, unsigned int&, nsOverflowContinuationTracker*) /builds/slave/m-cen-l64-asan-000000000000000/build/src/layout/generic/nsContainerFrame.cpp:998 #42 0x7f2064183839 in nsCanvasFrame::Reflow(nsPresContext*, nsHTMLReflowMetrics&, nsHTMLReflowState const&, unsigned int&) /builds/slave/m-cen-l64-asan-000000000000000/build/src/layout/generic/nsCanvasFrame.cpp:685 #43 0x7f206422c700 in ReflowChild /builds/slave/m-cen-l64-asan-000000000000000/build/src/layout/generic/nsContainerFrame.cpp:998 #44 0x7f206422c700 in nsHTMLScrollFrame::ReflowScrolledFrame(ScrollReflowState*, bool, bool, nsHTMLReflowMetrics*, bool) /builds/slave/m-cen-l64-asan-000000000000000/build/src/layout/generic/nsGfxScrollFrame.cpp:524 #45 0x7f206422db89 in nsHTMLScrollFrame::ReflowContents(ScrollReflowState*, nsHTMLReflowMetrics const&) /builds/slave/m-cen-l64-asan-000000000000000/build/src/layout/generic/nsGfxScrollFrame.cpp:636 #46 0x7f206422ff46 in nsHTMLScrollFrame::Reflow(nsPresContext*, nsHTMLReflowMetrics&, nsHTMLReflowState const&, unsigned int&) /builds/slave/m-cen-l64-asan-000000000000000/build/src/layout/generic/nsGfxScrollFrame.cpp:871 #47 0x7f206419e58e in nsContainerFrame::ReflowChild(nsIFrame*, nsPresContext*, nsHTMLReflowMetrics&, nsHTMLReflowState const&, int, int, unsigned int, unsigned int&, nsOverflowContinuationTracker*) /builds/slave/m-cen-l64-asan-000000000000000/build/src/layout/generic/nsContainerFrame.cpp:1040 #48 0x7f20643acf0f in ViewportFrame::Reflow(nsPresContext*, nsHTMLReflowMetrics&, nsHTMLReflowState const&, unsigned int&) /builds/slave/m-cen-l64-asan-000000000000000/build/src/layout/generic/nsViewportFrame.cpp:215 #49 0x7f206408eace in PresShell::DoReflow(nsIFrame*, bool) /builds/slave/m-cen-l64-asan-000000000000000/build/src/layout/base/nsPresShell.cpp:9070 #50 0x7f20640a24f8 in PresShell::ProcessReflowCommands(bool) /builds/slave/m-cen-l64-asan-000000000000000/build/src/layout/base/nsPresShell.cpp:9242 #51 0x7f20640a1a4a in PresShell::FlushPendingNotifications(mozilla::ChangesToFlush) /builds/slave/m-cen-l64-asan-000000000000000/build/src/layout/base/nsPresShell.cpp:4137 #52 0x7f2063ff648b in nsDocumentViewer::LoadComplete(nsresult) /builds/slave/m-cen-l64-asan-000000000000000/build/src/layout/base/nsDocumentViewer.cpp:932 #53 0x7f2064c59cbf in nsDocShell::EndPageLoad(nsIWebProgress*, nsIChannel*, nsresult) /builds/slave/m-cen-l64-asan-000000000000000/build/src/docshell/base/nsDocShell.cpp:7366 #54 0x7f2064c56333 in nsDocShell::OnStateChange(nsIWebProgress*, nsIRequest*, unsigned int, nsresult) /builds/slave/m-cen-l64-asan-000000000000000/build/src/docshell/base/nsDocShell.cpp:7185 #55 0x7f2064c5cddf in non-virtual thunk to nsDocShell::OnStateChange(nsIWebProgress*, nsIRequest*, unsigned int, nsresult) /builds/slave/m-cen-l64-asan-000000000000000/build/src/obj-firefox/docshell/base/Unified_cpp_docshell_base0.cpp:7192 #56 0x7f205f67aecb in nsDocLoader::DoFireOnStateChange(nsIWebProgress*, nsIRequest*, int&, nsresult) /builds/slave/m-cen-l64-asan-000000000000000/build/src/uriloader/base/nsDocLoader.cpp:1250 #57 0x7f205f67a1b3 in nsDocLoader::doStopDocumentLoad(nsIRequest*, nsresult) /builds/slave/m-cen-l64-asan-000000000000000/build/src/uriloader/base/nsDocLoader.cpp:831 #58 0x7f205f6773bf in nsDocLoader::DocLoaderIsEmpty(bool) /builds/slave/m-cen-l64-asan-000000000000000/build/src/uriloader/base/nsDocLoader.cpp:721 #59 0x7f205f679143 in nsDocLoader::OnStopRequest(nsIRequest*, nsISupports*, nsresult) /builds/slave/m-cen-l64-asan-000000000000000/build/src/uriloader/base/nsDocLoader.cpp:605 #60 0x7f205f679b7c in non-virtual thunk to nsDocLoader::OnStopRequest(nsIRequest*, nsISupports*, nsresult) /builds/slave/m-cen-l64-asan-000000000000000/build/src/obj-firefox/uriloader/base/Unified_cpp_uriloader_base0.cpp:609 #61 0x7f205e007079 in nsLoadGroup::RemoveRequest(nsIRequest*, nsISupports*, nsresult) /builds/slave/m-cen-l64-asan-000000000000000/build/src/netwerk/base/nsLoadGroup.cpp:640 #62 0x7f206035a4cc in nsDocument::DoUnblockOnload() /builds/slave/m-cen-l64-asan-000000000000000/build/src/dom/base/nsDocument.cpp:9068 #63 0x7f206035a16e in nsDocument::UnblockOnload(bool) /builds/slave/m-cen-l64-asan-000000000000000/build/src/dom/base/nsDocument.cpp:8996 #64 0x7f206032dc10 in nsDocument::DispatchContentLoadedEvents() /builds/slave/m-cen-l64-asan-000000000000000/build/src/dom/base/nsDocument.cpp:5163 #65 0x7f20603f46e0 in apply<nsDocument, void (nsDocument::*)()> /builds/slave/m-cen-l64-asan-000000000000000/build/src/obj-firefox/dom/base/../../dist/include/nsThreadUtils.h:661 #66 0x7f20603f46e0 in nsRunnableMethodImpl<void (nsDocument::*)(), true>::Run() /builds/slave/m-cen-l64-asan-000000000000000/build/src/obj-firefox/dom/base/../../dist/include/nsThreadUtils.h:868 #67 0x7f205de5975f in nsThread::ProcessNextEvent(bool, bool*) /builds/slave/m-cen-l64-asan-000000000000000/build/src/xpcom/threads/nsThread.cpp:960 #68 0x7f205ded281a in NS_ProcessNextEvent(nsIThread*, bool) /builds/slave/m-cen-l64-asan-000000000000000/build/src/xpcom/glue/nsThreadUtils.cpp:277 #69 0x7f205e7705e9 in mozilla::ipc::MessagePump::Run(base::MessagePump::Delegate*) /builds/slave/m-cen-l64-asan-000000000000000/build/src/ipc/glue/MessagePump.cpp:95 #70 0x7f205e6de4ec in RunInternal /builds/slave/m-cen-l64-asan-000000000000000/build/src/ipc/chromium/src/base/message_loop.cc:234 #71 0x7f205e6de4ec in RunHandler /builds/slave/m-cen-l64-asan-000000000000000/build/src/ipc/chromium/src/base/message_loop.cc:227 #72 0x7f205e6de4ec in MessageLoop::Run() /builds/slave/m-cen-l64-asan-000000000000000/build/src/ipc/chromium/src/base/message_loop.cc:201 #73 0x7f20637aa807 in nsBaseAppShell::Run() /builds/slave/m-cen-l64-asan-000000000000000/build/src/widget/nsBaseAppShell.cpp:156 #74 0x7f20655fa3e2 in XRE_RunAppShell /builds/slave/m-cen-l64-asan-000000000000000/build/src/toolkit/xre/nsEmbedFunctions.cpp:785 #75 0x7f205e6de4ec in RunInternal /builds/slave/m-cen-l64-asan-000000000000000/build/src/ipc/chromium/src/base/message_loop.cc:234 #76 0x7f205e6de4ec in RunHandler /builds/slave/m-cen-l64-asan-000000000000000/build/src/ipc/chromium/src/base/message_loop.cc:227 #77 0x7f205e6de4ec in MessageLoop::Run() /builds/slave/m-cen-l64-asan-000000000000000/build/src/ipc/chromium/src/base/message_loop.cc:201 #78 0x7f20655f9acc in XRE_InitChildProcess /builds/slave/m-cen-l64-asan-000000000000000/build/src/toolkit/xre/nsEmbedFunctions.cpp:621 #79 0x48d670 in content_process_main(int, char**) /builds/slave/m-cen-l64-asan-000000000000000/build/src/ipc/app/../contentproc/plugin-container.cpp:237 #80 0x7f205b809ec4 in __libc_start_main /build/buildd/eglibc-2.19/csu/libc-start.c:287 #81 0x48c9cc in _start (/home/symeon/Desktop/firefox/plugin-container+0x48c9cc) 0x6250002a1118 is located 2072 bytes inside of 8192-byte region [0x6250002a0900,0x6250002a2900) allocated by thread T0 (Web Content) here: #0 0x474fe1 in __interceptor_malloc /builds/slave/moz-toolchain/src/llvm/projects/compiler-rt/lib/asan/asan_malloc_linux.cc:74 #1 0x7f206b70de86 in PL_ArenaAllocate /builds/slave/m-cen-l64-asan-000000000000000/build/src/nsprpub/lib/ds/plarena.c:203 #2 0x7f2063dd8535 in nsPresArena::Allocate(unsigned int, unsigned long) /builds/slave/m-cen-l64-asan-000000000000000/build/src/layout/base/nsPresArena.cpp:165 #3 0x7f2063d0d2e5 in AllocateByObjectID /builds/slave/m-cen-l64-asan-000000000000000/build/src/layout/style/../base/nsPresArena.h:65 #4 0x7f2063d0d2e5 in PresShell /builds/slave/m-cen-l64-asan-000000000000000/build/src/layout/style/../base/nsIPresShell.h:255 #5 0x7f2063d0d2e5 in operator new /builds/slave/m-cen-l64-asan-000000000000000/build/src/layout/style/nsStyleStruct.h:1362 #6 0x7f2063d0d2e5 in nsRuleNode::ComputePositionData(void*, nsRuleData const*, nsStyleContext*, nsRuleNode*, nsRuleNode::RuleDetail, mozilla::RuleNodeCacheConditions) /builds/slave/m-cen-l64-asan-000000000000000/build/src/layout/style/nsRuleNode.cpp:7619 #7 0x7f2063ce8df3 in nsRuleNode::WalkRuleTree(nsStyleStructID, nsStyleContext*) /builds/slave/m-cen-l64-asan-000000000000000/build/src/layout/style/nsRuleNode.cpp:2407 #8 0x7f206419d8d8 in StylePosition /builds/slave/m-cen-l64-asan-000000000000000/build/src/obj-firefox/layout/generic/../../dist/include/nsStyleStructList.h:90 #9 0x7f206419d8d8 in nsContainerFrame::ComputeAutoSize(nsRenderingContext*, mozilla::WritingMode, mozilla::LogicalSize const&, int, mozilla::LogicalSize const&, mozilla::LogicalSize const&, mozilla::LogicalSize const&, bool) /builds/slave/m-cen-l64-asan-000000000000000/build/src/layout/generic/nsContainerFrame.cpp:912 #10 0x7f20641a8906 in nsFrame::ComputeSize(nsRenderingContext*, mozilla::WritingMode, mozilla::LogicalSize const&, int, mozilla::LogicalSize const&, mozilla::LogicalSize const&, mozilla::LogicalSize const&, nsIFrame::ComputeSizeFlags) /builds/slave/m-cen-l64-asan-000000000000000/build/src/layout/generic/nsFrame.cpp:4266 #11 0x7f2064170d77 in FloatMarginISize(nsHTMLReflowState const&, int, nsIFrame*, nsCSSOffsetState const&) /builds/slave/m-cen-l64-asan-000000000000000/build/src/layout/generic/nsBlockReflowState.cpp:688 #12 0x7f2064161c4a in nsBlockReflowState::FlowAndPlaceFloat(nsIFrame*) /builds/slave/m-cen-l64-asan-000000000000000/build/src/layout/generic/nsBlockReflowState.cpp:754 #13 0x7f206416fca6 in nsBlockReflowState::AddFloat(nsLineLayout*, nsIFrame*, int) /builds/slave/m-cen-l64-asan-000000000000000/build/src/layout/generic/nsBlockReflowState.cpp:629 #14 0x7f20640ea8f2 in GetOutermostLineLayout /builds/slave/m-cen-l64-asan-000000000000000/build/src/layout/generic/nsLineLayout.h:186 #15 0x7f20640ea8f2 in nsLineLayout::ReflowFrame(nsIFrame*, unsigned int&, nsHTMLReflowMetrics*, bool&) /builds/slave/m-cen-l64-asan-000000000000000/build/src/layout/generic/nsLineLayout.cpp:999 #16 0x7f2064154201 in nsBlockFrame::ReflowInlineFrame(nsBlockReflowState&, nsLineLayout&, nsLineList_iterator, nsIFrame*, LineReflowStatus*) /builds/slave/m-cen-l64-asan-000000000000000/build/src/layout/generic/nsBlockFrame.cpp:4035 #17 0x7f2064152a0d in nsBlockFrame::DoReflowInlineFrames(nsBlockReflowState&, nsLineLayout&, nsLineList_iterator, nsFlowAreaRect&, int&, nsFloatManager::SavedState*, bool*, LineReflowStatus*, bool) /builds/slave/m-cen-l64-asan-000000000000000/build/src/layout/generic/nsBlockFrame.cpp:3837 #18 0x7f20641491d2 in nsBlockFrame::ReflowInlineFrames(nsBlockReflowState&, nsLineList_iterator, bool*) /builds/slave/m-cen-l64-asan-000000000000000/build/src/layout/generic/nsBlockFrame.cpp:3703 #19 0x7f2064139591 in ReflowLine /builds/slave/m-cen-l64-asan-000000000000000/build/src/layout/generic/nsBlockFrame.cpp:2712 #20 0x7f2064139591 in nsBlockFrame::ReflowDirtyLines(nsBlockReflowState&) /builds/slave/m-cen-l64-asan-000000000000000/build/src/layout/generic/nsBlockFrame.cpp:2247 #21 0x7f2064131fc8 in nsBlockFrame::Reflow(nsPresContext*, nsHTMLReflowMetrics&, nsHTMLReflowState const&, unsigned int&) /builds/slave/m-cen-l64-asan-000000000000000/build/src/layout/generic/nsBlockFrame.cpp:1160 #22 0x7f206414fe47 in nsBlockReflowContext::ReflowBlock(mozilla::LogicalRect const&, bool, nsCollapsingMargin&, int, bool, nsLineBox*, nsHTMLReflowState&, unsigned int&, nsBlockReflowState&) /builds/slave/m-cen-l64-asan-000000000000000/build/src/layout/generic/nsBlockReflowContext.cpp:306 #23 0x7f2064145bad in nsBlockFrame::ReflowBlockFrame(nsBlockReflowState&, nsLineList_iterator, bool*) /builds/slave/m-cen-l64-asan-000000000000000/build/src/layout/generic/nsBlockFrame.cpp:3348 #24 0x7f20641395b3 in ReflowLine /builds/slave/m-cen-l64-asan-000000000000000/build/src/layout/generic/nsBlockFrame.cpp:2709 #25 0x7f20641395b3 in nsBlockFrame::ReflowDirtyLines(nsBlockReflowState&) /builds/slave/m-cen-l64-asan-000000000000000/build/src/layout/generic/nsBlockFrame.cpp:2247 #26 0x7f2064131fc8 in nsBlockFrame::Reflow(nsPresContext*, nsHTMLReflowMetrics&, nsHTMLReflowState const&, unsigned int&) /builds/slave/m-cen-l64-asan-000000000000000/build/src/layout/generic/nsBlockFrame.cpp:1160 #27 0x7f206419e1d1 in nsContainerFrame::ReflowChild(nsIFrame*, nsPresContext*, nsHTMLReflowMetrics&, nsHTMLReflowState const&, mozilla::WritingMode const&, mozilla::LogicalPoint const&, nsSize const&, unsigned int, unsigned int&, nsOverflowContinuationTracker*) /builds/slave/m-cen-l64-asan-000000000000000/build/src/layout/generic/nsContainerFrame.cpp:998 #28 0x7f2064188514 in nsColumnSetFrame::ReflowChildren(nsHTMLReflowMetrics&, nsHTMLReflowState const&, unsigned int&, nsColumnSetFrame::ReflowConfig const&, bool, nsCollapsingMargin*, nsColumnSetFrame::ColumnBalanceData&) /builds/slave/m-cen-l64-asan-000000000000000/build/src/layout/generic/nsColumnSetFrame.cpp:638 #29 0x7f206418c4bb in ReflowColumns /builds/slave/m-cen-l64-asan-000000000000000/build/src/layout/generic/nsColumnSetFrame.cpp:344 #30 0x7f206418c4bb in nsColumnSetFrame::Reflow(nsPresContext*, nsHTMLReflowMetrics&, nsHTMLReflowState const&, unsigned int&) /builds/slave/m-cen-l64-asan-000000000000000/build/src/layout/generic/nsColumnSetFrame.cpp:1075 #31 0x7f206414fe47 in nsBlockReflowContext::ReflowBlock(mozilla::LogicalRect const&, bool, nsCollapsingMargin&, int, bool, nsLineBox*, nsHTMLReflowState&, unsigned int&, nsBlockReflowState&) /builds/slave/m-cen-l64-asan-000000000000000/build/src/layout/generic/nsBlockReflowContext.cpp:306 #32 0x7f2064145bad in nsBlockFrame::ReflowBlockFrame(nsBlockReflowState&, nsLineList_iterator, bool*) /builds/slave/m-cen-l64-asan-000000000000000/build/src/layout/generic/nsBlockFrame.cpp:3348 #33 0x7f20641395b3 in ReflowLine /builds/slave/m-cen-l64-asan-000000000000000/build/src/layout/generic/nsBlockFrame.cpp:2709 #34 0x7f20641395b3 in nsBlockFrame::ReflowDirtyLines(nsBlockReflowState&) /builds/slave/m-cen-l64-asan-000000000000000/build/src/layout/generic/nsBlockFrame.cpp:2247 #35 0x7f2064131fc8 in nsBlockFrame::Reflow(nsPresContext*, nsHTMLReflowMetrics&, nsHTMLReflowState const&, unsigned int&) /builds/slave/m-cen-l64-asan-000000000000000/build/src/layout/generic/nsBlockFrame.cpp:1160 #36 0x7f206414fe47 in nsBlockReflowContext::ReflowBlock(mozilla::LogicalRect const&, bool, nsCollapsingMargin&, int, bool, nsLineBox*, nsHTMLReflowState&, unsigned int&, nsBlockReflowState&) /builds/slave/m-cen-l64-asan-000000000000000/build/src/layout/generic/nsBlockReflowContext.cpp:306 #37 0x7f2064145bad in nsBlockFrame::ReflowBlockFrame(nsBlockReflowState&, nsLineList_iterator, bool*) /builds/slave/m-cen-l64-asan-000000000000000/build/src/layout/generic/nsBlockFrame.cpp:3348 #38 0x7f20641395b3 in ReflowLine /builds/slave/m-cen-l64-asan-000000000000000/build/src/layout/generic/nsBlockFrame.cpp:2709 #39 0x7f20641395b3 in nsBlockFrame::ReflowDirtyLines(nsBlockReflowState&) /builds/slave/m-cen-l64-asan-000000000000000/build/src/layout/generic/nsBlockFrame.cpp:2247 SUMMARY: AddressSanitizer: use-after-poison /builds/slave/m-cen-l64-asan-000000000000000/build/src/obj-firefox/dom/html/../../dist/include/nsStyleStructList.h:101 nsIFrame::StyleDisplay() const Shadow bytes around the buggy address: 0x0c4a8004c1d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x0c4a8004c1e0: 00 00 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 0x0c4a8004c1f0: f7 f7 f7 f7 f7 00 00 00 00 00 00 00 00 00 00 00 0x0c4a8004c200: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x0c4a8004c210: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 f7 =>0x0c4a8004c220: f7 f7 f7[f7]f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 0x0c4a8004c230: f7 f7 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x0c4a8004c240: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x0c4a8004c250: 00 00 00 00 00 00 00 00 00 00 f7 f7 f7 f7 f7 f7 0x0c4a8004c260: f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 0x0c4a8004c270: f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 Shadow byte legend (one shadow byte represents 8 application bytes): Addressable: 00 Partially addressable: 01 02 03 04 05 06 07 Heap left redzone: fa Heap right redzone: fb Freed heap region: fd Stack left redzone: ==52781==ABORTING Am attaching the test case
Group: firefox-core-security → layout-core-security
Component: Untriaged → Layout
Product: Firefox → Core
Summary: Use-after-poison in nsFloatManager::GetFlowArea → Use-after-poison in nsFloatManager::GetFlowArea (with floats, multicol, and huge width)
Possibly the same underlying issue as bug 942794? (updating my ASAN tree now to take a look...)
Severity: normal → critical
Depends on: 942794
Keywords: crash
I don't think ASAN is needed to reproduce this -- ASAN just gives a more friendly crash message. But since this is a crash-on-poison, we should crash in the same way regardless of ASAN-ness. In a debug build, I get this output before crashing: nsBlockReflowContext: Block(div)(1)@7f7743963ea0 metrics=1073741824,6000! [Child 6240] ###!!! ASSERTION: letter frames and orthogonal floats with auto block-size shouldn't break, and if they do now, then they're breaking at the wrong point: 'NS_FRAME_IS_COMPLETE(reflowStatus)', file /layout/generic/nsBlockReflowState.cpp, line 778 nsBlockReflowContext: Block(div)(3)@7f7743964000 metrics=1073741824,6000! [Child 6240] ###!!! ASSERTION: letter frames and orthogonal floats with auto block-size shouldn't break, and if they do now, then they're breaking at the wrong point: 'NS_FRAME_IS_COMPLETE(reflowStatus)', file /layout/generic/nsBlockReflowState.cpp, line 778 nsBlockReflowContext: Block(div)(1)@7f7743964c10 metrics=1073741824,5400! [Child 6240] ###!!! ASSERTION: letter frames and orthogonal floats with auto block-size shouldn't break, and if they do now, then they're breaking at the wrong point: 'NS_FRAME_IS_COMPLETE(reflowStatus)', file /layout/generic/nsBlockReflowState.cpp, line 778 nsBlockReflowContext: Block(div)(1)@7f77439663d0 metrics=1073741824,6000! [Child 6240] ###!!! ASSERTION: letter frames and orthogonal floats with auto block-size shouldn't break, and if they do now, then they're breaking at the wrong point: 'NS_FRAME_IS_COMPLETE(reflowStatus)', file /layout/generic/nsBlockReflowState.cpp, line 778 nsBlockReflowContext: Block(div)(1)@7f77439665b8 metrics=1073741824,0! [Child 6240] ###!!! ASSERTION: letter frames and orthogonal floats with auto block-size shouldn't break, and if they do now, then they're breaking at the wrong point: 'NS_FRAME_IS_COMPLETE(reflowStatus)', file /layout/generic/nsBlockReflowState.cpp, line 778 nsBlockReflowContext: Block(div)(1)@7f77439665b8 metrics=1073741824,0! [Child 6240] ###!!! ASSERTION: letter frames and orthogonal floats with auto block-size shouldn't break, and if they do now, then they're breaking at the wrong point: 'NS_FRAME_IS_COMPLETE(reflowStatus)', file /layout/generic/nsBlockReflowState.cpp, line 778 nsBlockReflowContext: Block(div)(1)@7f7743966028 metrics=1073741824,6000! [Child 6240] ###!!! ASSERTION: letter frames and orthogonal floats with auto block-size shouldn't break, and if they do now, then they're breaking at the wrong point: 'NS_FRAME_IS_COMPLETE(reflowStatus)', file /layout/generic/nsBlockReflowState.cpp, line 778 nsBlockReflowContext: Block(div)(3)@7f7743964000 metrics=1073741824,6000! [Child 6240] ###!!! ASSERTION: letter frames and orthogonal floats with auto block-size shouldn't break, and if they do now, then they're breaking at the wrong point: 'NS_FRAME_IS_COMPLETE(reflowStatus)', file /layout/generic/nsBlockReflowState.cpp, line 778 nsBlockReflowContext: Block(div)(1)@7f77439665b8 metrics=1073741824,0! [Child 6240] ###!!! ASSERTION: letter frames and orthogonal floats with auto block-size shouldn't break, and if they do now, then they're breaking at the wrong point: 'NS_FRAME_IS_COMPLETE(reflowStatus)', file /layout/generic/nsBlockReflowState.cpp, line 778 nsBlockReflowContext: Block(div)(1)@7f7743966cc8 metrics=1073741824,2400! nsBlockReflowContext: Block(div)(3)@7f7743964000 metrics=1073741824,14400! nsBlockReflowContext: Block(div)(1)@7f77439665b8 metrics=1073741824,3000! nsBlockReflowContext: Block(div)(1)@7f7743964c10 metrics=1073741824,14400! And then I crash, in nsFloatManager::GetFlowArea calling into nsIFrame::StyleDisplay, on a poisoned nsIFrame object. The frame looks like this: p/x *fi.mFrame $6 = { <nsQueryFrame> = { _vptr$nsQueryFrame = 0x7ffffffff0dea7ff }, members of nsIFrame: static kFrameIID = 0x28, static kPrincipalList = 0x1, [...] mContent = 0x7ffffffff0dea7ff, mStyleContext = 0x7ffffffff0dea7ff, mParent = 0x7ffffffff0dea7ff, mNextSibling = 0x7ffffffff0dea7ff, mPrevSibling = 0x7ffffffff0dea7ff, mState = 0x7ffffffff0dea7ff, [...] } Looks like all of the pointer-values are poison addresses (and we're crashing when we try to deref one of them, mStyleContext). So, I think this is successfully mitigated by frame poisoning.
(In reply to Mats Palmgren (:mats) from comment #1) > Possibly the same underlying issue as bug 942794? Seems like a good bet -- the underlying issue there was bug 913162, which seems related to the testcase here.
Group: layout-core-security
Status: UNCONFIRMED → NEW
Ever confirmed: true
Keywords: testcase
Keywords: sec-other
Our fuzzers are still seeing this issue.
Crash Signature: [@ nsFloatManager::GetFlowArea]
Flags: in-testsuite?
Attached file multicol-float.html

I've attached a simplified testcase. Actually the cause is the violation of pushed-float invariant in nsColumnSetFrame.

Under certain cases, it will reflow the content with a smaller height constraint when a bigger one has already overflowed. If the previous failure has pushed some float, then a smaller height constraint could make the prev-in-flow of those pushed floats overflow, thus violates the invariant of pushed-float.

I will submit a patch.

If a BSize is already infeasible, we should not try a smaller size. Because if
the previous failure leaves some pushed floats, a smaller try might make
the prev-in-flow of the pushed float overflow, which violates the invariant of
pushed float and may cause use-after-free and crash.

Hi Mats,

I'm not sure whether you're the correct person to review this patch, I set the reviewer to you because I found multiple comments from you in layout/generic code.

Could you assign this bug to me and review my patch? In case I got the reviewer wrong, could you forward the patch to a correct reviewer?

Thanks!

Flags: needinfo?(mats)
Assignee: nobody → violet.bugreport
Flags: needinfo?(mats)
Priority: -- → P3

Violet, maybe you should apply for Level 1 Commit Access so you can push to Try yourself?
https://wiki.mozilla.org/ReleaseEngineering/TryServer

Ok, I will file a request for level 1 access and run the test before submitting. I've just read the instruction page, it says I need a voucher to apply, would you vouch for me?

Regarding the bug, I'm not sure whether I have explained the root cause clearly on that page. A step-by-step explanation might be very lengthy, but the timeline can be quickly figured out by running $ MOZ_LOG=ColumnSet:4 ./mach run with some printf to track nsBlockFrame::Reflow, nsBlockFrame::SplitFloat, etc.

The oddity emerges when the bsize constraint goes from 40 to 19, just a few log messages before crash happens.

Flags: needinfo?(mats)

(In reply to violet.bugreport from comment #9)

Ok, I will file a request for level 1 access and run the test before submitting. I've just read the instruction page, it says I need a voucher to apply, would you vouch for me?

Sure. CC me on the bug.

Regarding the bug, I'm not sure whether I have explained the root cause clearly on that page. A step-by-step explanation might be very lengthy, but the timeline can be quickly figured out by running $ MOZ_LOG=ColumnSet:4 ./mach run with some printf to track nsBlockFrame::Reflow, nsBlockFrame::SplitFloat, etc.

I can't really review any changes unless I think I have a clear understanding what the problem is first. I can debug it myself of course but that may take some time.

Flags: needinfo?(mats)

The machine I use to debug firefox has some problems, so I need time to fix them before applying for try server access.

So I think it would be better to submit the update that I already tested a few days ago. Would you test it on the try server and review the change? Thanks!

Flags: needinfo?(mats)

Well, it passed tests on Linux at least:
https://treeherder.mozilla.org/#/jobs?repo=try&revision=6ffdbe718e26c854bd4ad98b2d15e602453359a8
As I said earlier, I'm not going to review this until I understand
what goes wrong in the frame tree with our current code. It would
help if you can try to explain it to me, otherwise I'll have to
debug it myself.

Flags: needinfo?(mats)

Ok, I will explain the oddity in the nsColumnSetFrame with a further reduced testcase by dropping the surrounding div around dev.float-L which causes an assertion failure (see my explanation in a comment on phabricator). So the testcase would be:

<div class="multicol-b">
  <div class="step"></div>
  <div class="float-L"></div>
</div>
  • 1px=60 logical unit. Both .step and .float-L have 1px height, thus it's totally 2px=120. And we need at least 40 BSize to place it in 3 columns (120 = 40 * 3).

  • At the beginning of the log, it's the outer multicol .multicol-a relowing the child #0 with availBSize=1699, float-R consumes 26px=1560, while the inner multicol has 1px border, which consumes 2*1px=120. So the availableContentBSize for the inner one only remains 1699 - 1560 - 120 = 19. But because of the lack of a std::min in initialization, it tries to reflow 40.

  • see the inline comments in the log

    // outer reflows child #0
    [Child 8618: Main Thread]: D/ColumnSet ReflowChildren: Reflowing child #0 0x7fe0ef551be8: availBSize=1699
    [00000003] nsBlockFrame:0x7fe0ef551be8 Reflow

    // .float-R reflows
    [00000004] nsBlockFrame:0x7fe0ef551d38 Reflow
    [00000004] nsBlockFrame:0x7fe0ef551d38 Reflow done

    // inner reflows
    [Child 8618: Main Thread]: D/ColumnSet ChooseColumnStrategy: numColumns=3, colISize=4000, expectedISizeLeftOver=0, colBSize=40, colGap=0

    // at this point, we only have 19 available, why try mColMaxBSize=40? To exceed 19 is pointless
    [Child 8618: Main Thread]: D/ColumnSet ReflowChildren: Doing column reflow pass: mLastBalanceBSize=40, mColMaxBSize=40, RTL=0, mBalanceColCount=3, mColISize=4000, mColGap=0

    [Child 8618: Main Thread]: D/ColumnSet ReflowChildren: Reflowing child #0 0x7fe0ef551df0: availBSize=40
    [00000004] nsBlockFrame:0x7fe0ef551df0 Reflow
    [00000005] nsBlockFrame:0x7fe0ef551f40 Reflow
    [00000005] nsBlockFrame:0x7fe0ef551f40 Reflow done
    [00000004] nsBlockFrame:0x7fe0ef551df0 Reflow done
    [Child 8618: Main Thread]: D/ColumnSet ReflowChildren: Reflowed child #0 0x7fe0ef551df0: status=[Complete=N,NIF=Y,Truncated=N,Break=N,FirstLetter=N], desiredSize=(4000,40), CarriedOutBEndMargin=0 (ignored)
    [Child 8618: Main Thread]: D/ColumnSet ReflowChildren: Next childOrigin.iCoord=4060
    [Child 8618: Main Thread]: D/ColumnSet ReflowChildren: Reflowing child #1 0x7fe0ef552398: availBSize=40
    [00000004] nsBlockFrame:0x7fe0ef552398 Reflow
    [00000005] nsBlockFrame:0x7fe0ef552450 Reflow
    [00000005] nsBlockFrame:0x7fe0ef552450 Reflow done
    [00000005] nsBlockFrame:0x7fe0ef551ff8 Reflow
    [00000005] nsBlockFrame:0x7fe0ef551ff8 Reflow done
    [00000004] nsBlockFrame 0x7fe0ef552398 SplitFloat 0x7fe0ef551ff8 -> 0x7fe0ef5522d0
    [00000004] nsBlockFrame:0x7fe0ef552398 Reflow done
    [Child 8618: Main Thread]: D/ColumnSet ReflowChildren: Reflowed child #1 0x7fe0ef552398: status=[Complete=O,NIF=Y,Truncated=N,Break=N,FirstLetter=N], desiredSize=(4000,40), CarriedOutBEndMargin=0 (ignored)
    [Child 8618: Main Thread]: D/ColumnSet ReflowChildren: Next childOrigin.iCoord=8060

    // Why inconsistent height? Both child #0 and #1 have 40, #2 only has 19?
    // That's because https://github.com/mozilla/gecko-dev/blob/master/layout/generic/nsColumnSetFrame.cpp#L712
    // the last column is unbounded, thus it takes all avail size, which is 19, which is smaller than the previous columns.
    // Now we take a look at float splitting state. 60+60 should be split into 3 column, thus (40)+(20+20)+(40),
    // So there is already a split for 60 -> 20 + 40.
    // An unfortunate consequence of the oddity here is that the 40 is further split into 40 -> 19 + 21, then
    // 21 is pushed to child#2 as a pushed-float, see splitting -> below.
    // After this reflow, we end up with split float 1ff8, 22d0, 2790
    [Child 8618: Main Thread]: D/ColumnSet ReflowChildren: Reflowing child #2 0x7fe0ef552558: availBSize=19
    [00000004] nsBlockFrame:0x7fe0ef552558 Reflow
    [00000005] nsBlockFrame:0x7fe0ef5522d0 Reflow
    [00000005] nsBlockFrame:0x7fe0ef5522d0 Reflow done
    -> [00000004] nsBlockFrame 0x7fe0ef552558 SplitFloat 0x7fe0ef5522d0 -> 0x7fe0ef552790
    [00000004] nsBlockFrame:0x7fe0ef552558 Reflow done
    [Child 8618: Main Thread]: D/ColumnSet ReflowChildren: Reflowed child #2 0x7fe0ef552558: status=[Complete=O,NIF=Y,Truncated=N,Break=N,FirstLetter=N], desiredSize=(4000,19), CarriedOutBEndMargin=0 (ignored)
    [Child 8618: Main Thread]: D/ColumnSet ReflowChildren: Done column reflow pass: Infeasible :(

    // Now it ends with an infeasible state, we arrive at https://github.com/mozilla/gecko-dev/blob/master/layout/generic/nsColumnSetFrame.cpp#L1111
    // Then we reflow at 19 since it's the available size. But we shouldn't have tried 40 in the first place
    [Child 8618: Main Thread]: D/ColumnSet FindBestBalanceBSize: KnownInfeasibleBSize=40, KnownFeasibleBSize=40
    [Child 8618: Main Thread]: D/ColumnSet ReflowChildren: Doing column reflow pass: mLastBalanceBSize=40, mColMaxBSize=19, RTL=0, mBalanceColCount=3, mColISize=4000, mColGap=0
    [Child 8618: Main Thread]: D/ColumnSet ReflowChildren: Reflowing child #0 0x7fe0ef551df0: availBSize=19
    [00000004] nsBlockFrame:0x7fe0ef551df0 Reflow
    [00000005] nsBlockFrame:0x7fe0ef551f40 Reflow
    [00000005] nsBlockFrame:0x7fe0ef551f40 Reflow done
    [00000004] nsBlockFrame:0x7fe0ef551df0 Reflow done
    [Child 8618: Main Thread]: D/ColumnSet ReflowChildren: Reflowed child #0 0x7fe0ef551df0: status=[Complete=N,NIF=Y,Truncated=N,Break=N,FirstLetter=N], desiredSize=(4000,19), CarriedOutBEndMargin=0 (ignored)
    [Child 8618: Main Thread]: D/ColumnSet ReflowChildren: Next childOrigin.iCoord=4060
    [Child 8618: Main Thread]: D/ColumnSet ReflowChildren: Reflowing child #1 0x7fe0ef552398: availBSize=19
    [00000004] nsBlockFrame:0x7fe0ef552398 Reflow
    [00000005] nsBlockFrame:0x7fe0ef552450 Reflow
    [00000005] nsBlockFrame:0x7fe0ef552450 Reflow done
    [00000004] nsBlockFrame:0x7fe0ef552398 Reflow done
    [Child 8618: Main Thread]: D/ColumnSet ReflowChildren: Reflowed child #1 0x7fe0ef552398: status=[Complete=N,NIF=Y,Truncated=N,Break=N,FirstLetter=N], desiredSize=(4000,19), CarriedOutBEndMargin=0 (ignored)
    [Child 8618: Main Thread]: D/ColumnSet ReflowChildren: Next childOrigin.iCoord=8060

    // first 2 children only consume 19+19=38 height, thus the first split float 1ff8 is entirely overflow in child#1,
    // child#2 drains it, but one of the split float (2790) in its next-in-flow chain is still in child#2's pushed-float list.
    [Child 8618: Main Thread]: D/ColumnSet ReflowChildren: Reflowing child #2 0x7fe0ef552558: availBSize=19
    [00000004] nsBlockFrame:0x7fe0ef552558 Reflow
    [00000004] nsBlockFrame:0x7fe0ef552558 DrainOverflowLines 0x7fe0ef551ff8 <- this one, overflow from child #1
    [00000004] nsBlockFrame:0x7fe0ef552558 DrainOverflowLines: nif=0x7fe0ef5522d0
    [00000004] nsBlockFrame:0x7fe0ef552558 DrainOverflowLines: nif=0x7fe0ef552790 <- this one, the third split float still in pushed float list of child#2, which violates assertion.
    Assertion failure: mFloats.ContainsFrame(nif), at layout/generic/nsBlockFrame.cpp:4756

  • Conclusion: we should not try a size that is greater than availableContentBSize in the first place, it's a wasted computation at best. It will also make some previously overflow-but-not-drained frames hanging around to do bad things.

Flags: needinfo?(mats)

My updated patch is to address this problem. As a note, the original code will theoretically produce a wrong layout. Suppose we have 118 content to lay out in 3 columns, with an availableContentBSize 39 after a previously successful reflow (in order to have mLastBalanceBSize=40 so that the first try will start at 40). Then with original code it will be 118 = 40 + 40 + 38 with a feasible state. But the correct layout should respect the constraint and produce 118 = 39 + 39 + 39, with 1 overflow. This is quite theoretical, since a couple of logical unit can hardly have visible effect.

Hi Mats,

It's just a kind reminder that this patch I submitted half a month a ago is waiting for your review. I've already explained the timeline of this bug with logging message in a previous comment.

Could you review this patch now? Or if you don't have time, could point me to someone who is also eligible to review this patch? I'm afraid I would probably forget some of the detail in the bug if it takes too long.

Sorry for the delay, some other bugs required my attention.
I'm debugging this now so I'll get back to you soon...

Hi Mats,

Do you have further update of your reviewing? If you have any questions about this bug and my patch, feel free to ask me.

Attached file frame dumps

So here's my initial analysis of what happens in the frame tree
that leads up to the crash. I've colorized the interesting float
continuation chain, and numbered the interesting frames dumps
in a grey background color and numbered them. Referring to
each of the numbered trees in this log:

  1. initially we have a float in the first column
  2. we reflow and find that it overflows (but its parent is complete),
    so we put a NIF for it on the OverflowContainersList
  3. when reflowing the next column, we find that it still doesn't
    fit so we create another NIF and put it on the PushedFloatsList
    and create a continuation for the parent on ExcessOverflowContainersList

CRASH
Now backtracking a bit in rr to see what happens between 3 and the crash...

  1. This is the frame tree we start with when reflowing our float (red).
    Note that the inner ColumnSet has a NIF at this point.
  2. Backtracking to where we create that ColumnSet NIF.
    I think this is the point where things start to go wrong.
    We've decided that the float's parent doesn't fit in in this
    column at all and we push the lines containing it (creating
    the Overflow-lines list) and create the NIF.
  3. At this point the NIF has picked up the Overflow-lines so
    the float first-in-flow is in the ColumnSet NIF and its continuations
    in the previous ColumnSet. Likewise for the float's parent block
    which is also in the wrong order. This seems questionable to me.
    Technically, we would either be COMPLETE, in which case we'd delete
    the NIFs, or INCOMPLETE, in which case we'd push them, but still...

From 6, this is essentially what happens, we decide it's COMPLETE
and delete the NIFs. The reason we crash is that one of the float
NIFs are registered in the float manager, and we try to use it
after it's been deleted (frame-poisoning makes it non-exploitable
though).

(my apologies for the verbosity of this log)

Flags: needinfo?(mats)
Attachment #9055835 - Attachment mime type: application/octet-stream → text/html

I wrote a WIP to fix the underlying cause of the crash here:
https://hg.mozilla.org/try/rev/36932abd37ac11308bfee0068ef5eaf74e9f7846
If a continuation pulls in children from its prev-in-flow
then it should also move any overflow containers for those
from its OverflowContainers list, to avoid the child
continuations from becoming in the wrong order.
The WIP currently moves them to the principal child list
(mFrames), but ExcessOverflowContainers might be better.
I'll investigate this some more...

FTR, there's one more detail I want to highlight in the log above.
At the very end, I print out nsFloatManager::mFloats. We have
the (float) child of the overflow container (green) at index 0,
and the (red) child float from the line list in slot 1. This is
because we call ReflowOverflowContainerChildren before reflowing
the principal children (in the lines), so it's added first.
The stack when we add that float is:

#0 nsTArray_Impl<nsFloatManager::FloatInfo, nsTArrayInfallibleAllocator>::AppendElement
#1 nsFloatManager::AddFloat
#2 mozilla::BlockReflowInput::FlowAndPlaceFloat
#3 nsBlockFrame::ReflowPushedFloats
#4 nsBlockFrame::Reflow
#5 nsContainerFrame::ReflowChild
#6 nsContainerFrame::ReflowOverflowContainerChildren
#7 nsBlockFrame::Reflow

So after we reflow the red float and find that it's COMPLETE
and destroy its continuations, we have a dead continuation
in the float manager.

Hope you don't mind if I steal this one Violet. I'd like to fix
the underlying crash here separately from any sizing changes.
Please file a follow-up bug with your patch since it might give
more correct layout results. Thanks.

Assignee: violet.bugreport → mats
Pushed by mpalmgren@mozilla.com: https://hg.mozilla.org/integration/mozilla-inbound/rev/204d0d6a487f Move [Excess]OverflowContainers continuations of children we pull in from our prev-in-flow to our principal list to avoid making them unordered. r=dholbert
Status: NEW → RESOLVED
Closed: 7 years ago
Resolution: --- → FIXED
Target Milestone: --- → mozilla68
Attachment #9047943 - Attachment is obsolete: true
Whiteboard: [adv-main68-]
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: