From 080e18fa4748456003164f58b0d925b8c3826a67 Mon Sep 17 00:00:00 2001 From: Daniel Holbert Date: Thu, 13 Jan 2022 06:08:51 +0000 Subject: [PATCH] Bug 1663722: Make nsPageSequenceFrame gracefully handle SizeToContent calls. r=emilio nsPageSequenceFrame does a thing where it grows its desired size to fit the AvailableISize and ComputedBSize (under the assumption that those are the actual dimensions of our scrollport, which it wants to make maximal use of). This behavior causes trouble when it's reflowed under the privileged 'sizeToContent' JS API. That API makes us reflow with nscoord_MAX as the viewport's ComputedBSize(), and this nscoord_MAX value gets passed down to be the nsPageSequenceFrame's ComputedBSize as well. When we reach the code in question, we dutifully grow the desired size to that bogus huge value, which is clearly wrong. This patch addresses this issue by simply declining to grow the desired size in the scenario where ComputedBSize() is unconstrained. This leaves us with reasonable values for our desired size (which are actually based on the content, which makes it the right thing to do for the purpose of a SizeToContent() call). Differential Revision: https://phabricator.services.mozilla.com/D135762 --- layout/generic/nsPageSequenceFrame.cpp | 18 ++++++++++++++++-- layout/printing/crashtests/1663722.html | 11 +++++++++++ layout/printing/crashtests/crashtests.list | 1 + 3 files changed, 28 insertions(+), 2 deletions(-) create mode 100644 layout/printing/crashtests/1663722.html diff --git a/layout/generic/nsPageSequenceFrame.cpp b/layout/generic/nsPageSequenceFrame.cpp index 67be1dea2923..31a64400791b 100644 --- a/layout/generic/nsPageSequenceFrame.cpp +++ b/layout/generic/nsPageSequenceFrame.cpp @@ -190,10 +190,21 @@ void nsPageSequenceFrame::PopulateReflowOutput( nscoord iSize = wm.IsVertical() ? mSize.Height() : mSize.Width(); nscoord bSize = wm.IsVertical() ? mSize.Width() : mSize.Height(); + nscoord availableISize = aReflowInput.AvailableISize(); + nscoord computedBSize = aReflowInput.ComputedBSize(); + if (MOZ_UNLIKELY(computedBSize == NS_UNCONSTRAINEDSIZE)) { + // We have unconstrained BSize, which should only happen if someone calls + // SizeToContent() on our window (which we don't expect to happen for + // actual user flows, but is possible for fuzzers to trigger). We just nerf + // the ReflowInput's contributions to the std::max() expressions below, + // which does indeed make us "size to content", via letting std::max() + // choose the scaled iSize/bSize expressions. + availableISize = computedBSize = 0; + } aReflowOutput.ISize(wm) = - std::max(NSToCoordFloor(iSize * scale), aReflowInput.AvailableISize()); + std::max(NSToCoordFloor(iSize * scale), availableISize); aReflowOutput.BSize(wm) = - std::max(NSToCoordFloor(bSize * scale), aReflowInput.ComputedBSize()); + std::max(NSToCoordFloor(bSize * scale), computedBSize); aReflowOutput.SetOverflowAreasToDesiredBounds(); } @@ -275,6 +286,9 @@ void nsPageSequenceFrame::Reflow(nsPresContext* aPresContext, // When we're displayed on-screen, the computed size that we're given is // the size of our scrollport. We need to save this for use in // GetPrintPreviewScale. + // (NOTE: It's possible but unlikely that we have an unconstrained BSize + // here, if we're being sized to content. GetPrintPreviewScale() checks + // for and handles this, when making use of this member-var.) mScrollportSize = aReflowInput.ComputedSize(); } diff --git a/layout/printing/crashtests/1663722.html b/layout/printing/crashtests/1663722.html new file mode 100644 index 000000000000..aa20d8fa60d7 --- /dev/null +++ b/layout/printing/crashtests/1663722.html @@ -0,0 +1,11 @@ + + + + + diff --git a/layout/printing/crashtests/crashtests.list b/layout/printing/crashtests/crashtests.list index ea0a76de892e..094502ed0fa2 100644 --- a/layout/printing/crashtests/crashtests.list +++ b/layout/printing/crashtests/crashtests.list @@ -3,4 +3,5 @@ load 509839-2.html load 576878.xhtml asserts-if(Android,0-1) load 793844.html skip-if(Android) load 1662259.html +skip-if(Android) load 1663722.html skip-if(Android) load 1671503.html