Bug 121020

Summary: Crash on shape-outside when using calc()
Product: WebKit Reporter: Dirk Schulze <krit>
Component: CSSAssignee: Hans Muller <giles_joplin>
Status: RESOLVED FIXED    
Severity: Normal CC: bjonesbe, buildbot, commit-queue, esprehn+autocc, giles_joplin, glenn, koivisto, macpherson, menard, rniwa
Priority: P2    
Version: 528+ (Nightly build)   
Hardware: Unspecified   
OS: Unspecified   
Bug Depends on:    
Bug Blocks: 122036    
Attachments:
Description Flags
Crash test
none
Patch
buildbot: commit-queue-
Archive of layout-test-results from webkit-ews-14 for mac-mountainlion-wk2
none
Archive of layout-test-results from webkit-ews-07 for mac-mountainlion
none
Archive of layout-test-results from webkit-ews-03 for mac-mountainlion
none
Patch
krit: review-
Patch
krit: review+, krit: commit-queue-
Patch none

Dirk Schulze
Reported 2013-09-08 23:19:56 PDT
Created attachment 211010 [details] Crash test When a users specifies the shape-outside property with calc(), the browser crashes: -webkit-shape-outside: circle(50%, 50%, calc(50% - 20px)); Stack: 1 0x10778a4d0 WTFCrash 2 0x109664cfd WebCore::floatValueForLength(WebCore::Length const&, float, WebCore::RenderView*) 3 0x109c08029 WebCore::Shape::createShape(WebCore::BasicShape const*, WebCore::LayoutSize const&, WebCore::WritingMode, WebCore::Length, WebCore::Length) 4 0x109c0b115 WebCore::ShapeInfo<WebCore::RenderBlock, &(WebCore::RenderStyle::resolvedShapeInside() const), &(WebCore::Shape::getIncludedIntervals(WebCore::LayoutUnit, WebCore::LayoutUnit, WTF::Vector<WebCore::LineSegment, 0ul, WTF::CrashOnOverflow>&) const)>::computedShape() const 5 0x1098712b1 WebCore::ShapeInsideInfo::computedShapeLogicalBoundingBox() const 6 0x10986d251 WebCore::ShapeInfo<WebCore::RenderBlock, &(WebCore::RenderStyle::resolvedShapeInside() const), &(WebCore::Shape::getIncludedIntervals(WebCore::LayoutUnit, WebCore::LayoutUnit, WTF::Vector<WebCore::LineSegment, 0ul, WTF::CrashOnOverflow>&) const)>::shapeLogicalTop() const 7 0x10987881b WebCore::RenderBlock::layoutRunsAndFloatsInRange(WebCore::LineLayoutState&, WebCore::BidiResolver<WebCore::InlineIterator, WebCore::BidiRun>&, WebCore::InlineIterator const&, WebCore::BidiStatus const&, unsigned int) BasicShapeFunction.cpp:114 static Length convertToLength(... does not have CalculatedConversion as possible type.
Attachments
Crash test (460 bytes, text/html)
2013-09-08 23:19 PDT, Dirk Schulze
no flags
Patch (76.29 KB, patch)
2013-09-26 17:32 PDT, Hans Muller
buildbot: commit-queue-
Archive of layout-test-results from webkit-ews-14 for mac-mountainlion-wk2 (463.44 KB, application/zip)
2013-09-26 18:22 PDT, Build Bot
no flags
Archive of layout-test-results from webkit-ews-07 for mac-mountainlion (541.34 KB, application/zip)
2013-09-26 19:02 PDT, Build Bot
no flags
Archive of layout-test-results from webkit-ews-03 for mac-mountainlion (477.80 KB, application/zip)
2013-09-26 20:01 PDT, Build Bot
no flags
Patch (77.34 KB, patch)
2013-09-27 07:22 PDT, Hans Muller
krit: review-
Patch (79.24 KB, patch)
2013-09-27 12:28 PDT, Hans Muller
krit: review+
krit: commit-queue-
Patch (79.34 KB, patch)
2013-09-27 15:39 PDT, Hans Muller
no flags
Dirk Schulze
Comment 1 2013-09-16 11:14:10 PDT
There was a report on chromium at http://code.google.com/p/chromium/issues/detail?id=277799 as well.
Hans Muller
Comment 2 2013-09-18 11:47:47 PDT
As Dirk pointed out, the fix for the immediate problem is trivial. Just add CalculatedConversion to the convertToLength() supportTypes template parameter in BasicShapeFunctions.cpp/convertToLength(). And similarly, this exposes a lacuna in CSSPrimitiveValue::CSSPrimitiveValue(const Length&) window.getComputedStyle(document.getElementById("shape-inside"))["-webkit-shape-inside"] [CRASH] frame #6: 0x0000000104c9777f WebCore`WebCore::ComputedStyleExtractor::propertyValue(WebCore::CSSPropertyID, WebCore::EUpdateLayout) const + 47759 at CSSComputedStyleDeclaration.cpp:2847 2844 return cssValuePool().createIdentifierValue(CSSValueNone); 2845 } 2846 ASSERT(style->shapeInside()->type() == ShapeValue::Shape); -> 2847 return valueForBasicShape(style->shapeInside()->shape()); 2848 case CSSPropertyWebkitShapeOutside: 2849 if (!style->shapeOutside()) 2850 return cssValuePool().createIdentifierValue(CSSValueAuto); The valueForBasicShape() implementation uses CSSValuePool.createValue() which uses the aforementioned CSSPrimitiveValue() constructor. The constructor fails because it's currently unsupported for Lengths whose type is CALCULATED. CSSPrimitiveValue::CSSPrimitiveValue(const Length& length) { ... case Calculated: case Relative: case Undefined: ASSERT_NOT_REACHED(); break; } This issue appears to have been addressed in Blink, see http://src.chromium.org/viewvc/blink?view=revision&revision=156683
Hans Muller
Comment 3 2013-09-26 17:32:19 PDT
Created attachment 212774 [details] Patch This change prevents a crash caused by specifying a CSS Shape geometry Length attribute with a calc() expression. It adds support for converting Lengths to CSSPrimitive Values, in large part by migrating Blink changes made to the calc classes since the split. Doing so required a few supporting changes in some related classes, notably CSSPrimitiveValue.
Build Bot
Comment 4 2013-09-26 18:22:17 PDT
Comment on attachment 212774 [details] Patch Attachment 212774 [details] did not pass mac-wk2-ews (mac-wk2): Output: http://webkit-queues.appspot.com/results/2629043 New failing tests: css3/calc/cssom.html
Build Bot
Comment 5 2013-09-26 18:22:19 PDT
Created attachment 212778 [details] Archive of layout-test-results from webkit-ews-14 for mac-mountainlion-wk2 The attached test failures were seen while running run-webkit-tests on the mac-wk2-ews. Bot: webkit-ews-14 Port: mac-mountainlion-wk2 Platform: Mac OS X 10.8.5
Build Bot
Comment 6 2013-09-26 19:02:08 PDT
Comment on attachment 212774 [details] Patch Attachment 212774 [details] did not pass mac-ews (mac): Output: http://webkit-queues.appspot.com/results/2632042 New failing tests: css3/calc/cssom.html
Build Bot
Comment 7 2013-09-26 19:02:11 PDT
Created attachment 212785 [details] Archive of layout-test-results from webkit-ews-07 for mac-mountainlion The attached test failures were seen while running run-webkit-tests on the mac-ews. Bot: webkit-ews-07 Port: mac-mountainlion Platform: Mac OS X 10.8.5
Build Bot
Comment 8 2013-09-26 20:01:27 PDT
Comment on attachment 212774 [details] Patch Attachment 212774 [details] did not pass mac-ews (mac): Output: http://webkit-queues.appspot.com/results/2652011 New failing tests: css3/calc/cssom.html
Build Bot
Comment 9 2013-09-26 20:01:30 PDT
Created attachment 212786 [details] Archive of layout-test-results from webkit-ews-03 for mac-mountainlion The attached test failures were seen while running run-webkit-tests on the mac-ews. Bot: webkit-ews-03 Port: mac-mountainlion Platform: Mac OS X 10.8.5
Hans Muller
Comment 10 2013-09-27 07:22:39 PDT
Created attachment 212805 [details] Patch Updated the expected results for /css3/calc/cssom.html. Fixed the LayoutTests ChangeLog entry.
Dirk Schulze
Comment 11 2013-09-27 09:06:39 PDT
Comment on attachment 212805 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=212805&action=review Thanks for all the work Hans! Great back porting patch. And thanks for cleaning up the source code as well. Just some snippets inside. Really just minor things but I would like to look over the patch again. > LayoutTests/css3/calc/cssom-expected.txt:12 > -100px * (1 + 2 * 3 - 4 / 5) => calc(100px * ((1 + (2 * 3)) - (4 / 5))) > -(100px) + 200px => calc(100px + 200px) > +100px * (1 + 2 * 3 - 4 / 5) => calc(620px) > +(100px) + 200px => calc(300px) Do we have nested calc's as well? This is important if you animate from one calc function to a real value on CSS Shapes. So we need a test for that. I believe a small test calc(5px + calc(3px * 5%)) is sufficient enough. > Source/WebCore/css/BasicShapeFunctions.cpp:41 > +static PassRefPtr<CSSPrimitiveValue> convertToCSSPrimitiveValue(const RenderStyle* style, const Length& length) This function actually makes the calls longer. Compare the both: pool.createValue(rectangle->x(), style); convertToCSSPrimitiveValue(style, rectangle->x()) It doesn't look like it is worth it and you have to look at another place to see what is going on as well. I suggest removing this function again. > Source/WebCore/css/BasicShapeFunctions.cpp:121 > + return value->convertToLength<CalculatedConversion | FixedIntegerConversion | FixedFloatConversion | PercentConversion | ViewportPercentageConversion>(style, rootStyle, style->effectiveZoom()); I think CalculatedConversion is lined up after PercentConversion every where else. Just a snippet, but makes search and replace easier later when we refactor the code :D > Source/WebCore/css/CSSCalculationValue.cpp:273 > + One newline too many. > Source/WebCore/css/CSSCalculationValue.cpp:292 > + ASSERT_NOT_REACHED(); We already have the assertion in the switch, you'll never reach it. > Source/WebCore/css/CSSCalculationValue.cpp:326 > +/* CalcNumber */ { CalcNumber, CalcOther, CalcPercentNumber, CalcPercentNumber, CalcOther }, > +/* CalcLength */ { CalcOther, CalcLength, CalcPercentLength, CalcOther, CalcPercentLength }, > +/* CalcPercent */ { CalcPercentNumber, CalcPercentLength, CalcPercent, CalcPercentNumber, CalcPercentLength }, > +/* CalcPercentNumber */ { CalcPercentNumber, CalcOther, CalcPercentNumber, CalcPercentNumber, CalcOther }, > +/* CalcPercentLength */ { CalcOther, CalcPercentLength, CalcPercentLength, CalcOther, CalcPercentLength }, Do you mind if you add these comments at the end of each line? > Source/WebCore/css/CSSCalculationValue.cpp:362 > + // Not testing for actual integer values. I don't understand this comment. > Source/WebCore/css/CSSCalculationValue.cpp:383 > + static PassRefPtr<CSSCalcExpressionNode> createSimplified(PassRefPtr<CSSCalcExpressionNode> leftSide, PassRefPtr<CSSCalcExpressionNode> rightSide, CalcOperator op) Wow! This function is massive! Do we have tests for special cases like calc(a + b / calc(d * calc(e + f))) ? > Source/WebCore/css/CSSCalculationValue.cpp:748 > + // FIXME(crbug.com/269320): Create a CSSCalcExpressionNode equivalent of CalcExpressionBlendLength. Hmmm. I am not sure if we should leave that in WebKit source code. I think we have a WebKit bug for it already. Can you search it and replace the comment with the webkit bug please? > Source/WebCore/css/CSSCalculationValue.cpp:795 > + ASSERT_NOT_REACHED(); I am unsure if we should leave these assertions. But maybe we should if someone forgets to add an return. But then we should remove the assertion and return in case Undefined:. (Same with the other switches)
Hans Muller
Comment 12 2013-09-27 12:17:58 PDT
(In reply to comment #11) > (From update of attachment 212805 [details]) > View in context: https://bugs.webkit.org/attachment.cgi?id=212805&action=review > > > LayoutTests/css3/calc/cssom-expected.txt:12 > > -100px * (1 + 2 * 3 - 4 / 5) => calc(100px * ((1 + (2 * 3)) - (4 / 5))) > > -(100px) + 200px => calc(100px + 200px) > > +100px * (1 + 2 * 3 - 4 / 5) => calc(620px) > > +(100px) + 200px => calc(300px) > > Do we have nested calc's as well? This is important if you animate from one calc function to a real value on CSS Shapes. So we need a test for that. I believe a small test calc(5px + calc(3px * 5%)) is sufficient enough. We don't have nested calc's yet. > > Source/WebCore/css/CSSCalculationValue.cpp:292 > > + ASSERT_NOT_REACHED(); > > We already have the assertion in the switch, you'll never reach it. I agree however I think it's there to keep the Windows compiler from failing. I think there was a discussion about this on webkit-dev recently although I haven't been able to find it. > > Source/WebCore/css/CSSCalculationValue.cpp:362 > > + // Not testing for actual integer values. > > I don't understand this comment. I think it's drawing a distinction between the calc() "resolved type" of the expression and the actual type of the result. For example the result of 4/2 is not an integer per the spec. I don't think this part of the comment is useful (the spec reference below it is), so I've removed it. > > Source/WebCore/css/CSSCalculationValue.cpp:383 > > + static PassRefPtr<CSSCalcExpressionNode> createSimplified(PassRefPtr<CSSCalcExpressionNode> leftSide, PassRefPtr<CSSCalcExpressionNode> rightSide, CalcOperator op) > > Wow! This function is massive! Do we have tests for special cases like calc(a + b / calc(d * calc(e + f))) ? Good point. I'd forgotten to migrate the test added to check the new simplification code. > > > Source/WebCore/css/CSSCalculationValue.cpp:748 > > + // FIXME(crbug.com/269320): Create a CSSCalcExpressionNode equivalent of CalcExpressionBlendLength. > > Hmmm. I am not sure if we should leave that in WebKit source code. I think we have a WebKit bug for it already. Can you search it and replace the comment with the webkit bug please? I wasn't able to locate an existing bug for this. I've removed the Blink bug reference for now.
Hans Muller
Comment 13 2013-09-27 12:28:40 PDT
Created attachment 212834 [details] Patch Made the suggested changes.
Bem Jones-Bey
Comment 14 2013-09-27 12:30:39 PDT
Comment on attachment 212805 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=212805&action=review >>> Source/WebCore/css/CSSCalculationValue.cpp:292 >>> + ASSERT_NOT_REACHED(); >> >> We already have the assertion in the switch, you'll never reach it. > > I agree however I think it's there to keep the Windows compiler from failing. I think there was a discussion about this on webkit-dev recently although I haven't been able to find it. It's Qt, actually. Here's the thread: https://lists.webkit.org/pipermail/webkit-dev/2013-September/025422.html
Dirk Schulze
Comment 15 2013-09-27 12:59:30 PDT
Comment on attachment 212834 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=212834&action=review Great patch. Just a snippet. r+ > Source/WebCore/css/CSSCalculationValue.cpp:746 > + // FIXME: Create a CSSCalcExpressionNode equivalent of CalcExpressionBlendLength. If this bug does not exist yet, please create it and add the link in the comment.
Hans Muller
Comment 16 2013-09-27 15:24:58 PDT
(In reply to comment #15) > (From update of attachment 212834 [details]) > View in context: https://bugs.webkit.org/attachment.cgi?id=212834&action=review > > Great patch. Just a snippet. r+ > > > Source/WebCore/css/CSSCalculationValue.cpp:746 > > + // FIXME: Create a CSSCalcExpressionNode equivalent of CalcExpressionBlendLength. > > If this bug does not exist yet, please create it and add the link in the comment. I created a WebKit version of the Bink bug, it's https://bugs.webkit.org/show_bug.cgi?id=122036
Hans Muller
Comment 17 2013-09-27 15:39:31 PDT
Created attachment 212846 [details] Patch Added the FIXME bug URL.
WebKit Commit Bot
Comment 18 2013-09-27 16:16:18 PDT
Comment on attachment 212846 [details] Patch Clearing flags on attachment: 212846 Committed r156586: <http://trac.webkit.org/changeset/156586>
WebKit Commit Bot
Comment 19 2013-09-27 16:16:25 PDT
All reviewed patches have been landed. Closing bug.
Antti Koivisto
Comment 20 2013-11-07 01:32:47 PST
Comment on attachment 212846 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=212846&action=review > Source/WebCore/css/CSSValuePool.h:55 > + PassRefPtr<CSSPrimitiveValue> createValue(const Length& value, const RenderStyle* style) { return CSSPrimitiveValue::create(value, style); } A value with style? How does that make sense?
Hans Muller
Comment 21 2013-11-07 11:50:38 PST
(In reply to comment #20) > (From update of attachment 212846 [details]) > View in context: https://bugs.webkit.org/attachment.cgi?id=212846&action=review > > > Source/WebCore/css/CSSValuePool.h:55 > > + PassRefPtr<CSSPrimitiveValue> createValue(const Length& value, const RenderStyle* style) { return CSSPrimitiveValue::create(value, style); } > > A value with style? How does that make sense? To c(In reply to comment #20) > (From update of attachment 212846 [details]) > View in context: https://bugs.webkit.org/attachment.cgi?id=212846&action=review > > > Source/WebCore/css/CSSValuePool.h:55 > > + PassRefPtr<CSSPrimitiveValue> createValue(const Length& value, const RenderStyle* style) { return CSSPrimitiveValue::create(value, style); } > > A value with style? How does that make sense? It's really just there to provide access to the style's effectiveZoom, which is needed to compute the value of pixel type lengths. The CSSPrimitiveValue doesn't actually hang on to the style.
Note You need to log in before you can comment on or make changes to this bug.