Ignore:
Timestamp:
Sep 27, 2013, 4:17:34 PM (12 years ago)
Author:
[email protected]
Message:

Crash on shape-outside when using calc()
https://bugs.webkit.org/show_bug.cgi?id=121020

Reviewed by Dirk Schulze.

Source/WebCore:

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.

Tests: fast/shapes/shape-inside/shape-inside-calc-crash.html

css3/calc/simplification.html

  • css/BasicShapeFunctions.cpp:

(WebCore::convertToCSSPrimitiveValue): Effectively use the new CSSPrimtiveValue(length,style) constructor to convert Lengths to CSSValues.
(WebCore::valueForBasicShape): Use the convertToCSSPrimitiveValue() function.
(WebCore::convertToLength): Added the CalculatedConversion convertToLength() flag to enable support for calc() valued Length Shape attributes.

  • css/BasicShapeFunctions.h:
  • css/CSSCalculationValue.cpp:

(WebCore::hasDoubleValue):
(WebCore::buildCssText):
(WebCore::CSSCalcValue::clampToPermittedRange):
(WebCore::CSSCalcValue::doubleValue):
(WebCore::CSSCalcExpressionNode::~CSSCalcExpressionNode):
(WebCore::CSSCalcPrimitiveValue::create):
(WebCore::CSSCalcPrimitiveValue::toCalcValue):
(WebCore::CSSCalcPrimitiveValue::doubleValue):
(WebCore::CSSCalcPrimitiveValue::computeLengthPx):
(WebCore::CSSCalcPrimitiveValue::primitiveType):
(WebCore::CSSCalcPrimitiveValue::CSSCalcPrimitiveValue):
(WebCore::determineCategory):
(WebCore::isIntegerResult):
(WebCore::CSSCalcBinaryOperation::create):
(WebCore::CSSCalcBinaryOperation::createSimplified):
(WebCore::CSSCalcBinaryOperation::doubleValue):
(WebCore::CSSCalcBinaryOperation::buildCssText):
(WebCore::CSSCalcBinaryOperation::primitiveType):
(WebCore::CSSCalcBinaryOperation::CSSCalcBinaryOperation):
(WebCore::CSSCalcBinaryOperation::getNumberSide):
(WebCore::CSSCalcBinaryOperation::evaluate):
(WebCore::CSSCalcBinaryOperation::evaluateOperator):
(WebCore::CSSCalcExpressionNodeParser::parseValue):
(WebCore::CSSCalcExpressionNodeParser::parseValueTerm):
(WebCore::CSSCalcExpressionNodeParser::parseValueMultiplicativeExpression):
(WebCore::CSSCalcExpressionNodeParser::parseAdditiveValueExpression):
(WebCore::CSSCalcValue::createExpressionNode):
(WebCore::CSSCalcValue::create):

  • css/CSSCalculationValue.h:

(WebCore::CSSCalcExpressionNode::category):
(WebCore::CSSCalcValue::create):
(WebCore::CSSCalcValue::isInt):
(WebCore::CSSCalcValue::permittedValueRange):
(WebCore::CSSCalcValue::expressionNode):
(WebCore::CSSCalcValue::CSSCalcValue):
(WebCore::toCSSCalcValue):

  • css/CSSComputedStyleDeclaration.cpp:

(WebCore::ComputedStyleExtractor::propertyValue): Pass the style along to the new valueForBasicShape() function.

  • css/CSSPrimitiveValue.cpp:

(WebCore::CSSPrimitiveValue::unitCategory): Made this function public so that CSSCalculationValue could use it.
(WebCore::CSSPrimitiveValue::conversionToCanonicalUnitsScaleFactor): Ditto.
(WebCore::CSSPrimitiveValue::primitiveType): Cleared trailing whitespace.
(WebCore::CSSPrimitiveValue::CSSPrimitiveValue): Construct a CSSPrimitiveValue from a Length and a RenderStyle*.
(WebCore::CSSPrimitiveValue::init): The common part of the two Length CSSPrimitiveValue constructors.
(WebCore::CSSPrimitiveValue::computeLengthDouble): Moved the case labels to the left per check-webkit-style.
(WebCore::CSSPrimitiveValue::getStringValue): Ditto.
(WebCore::CSSPrimitiveValue::getDoubleValue): Removed trailing whitespace.

  • css/CSSPrimitiveValue.h:

(WebCore::CSSPrimitiveValue::create): Construct a CSSPrimitiveValue from a Length and a RenderStyle*.
(WebCore::toCSSPrimitiveValue): Check the CSSValue*'s validity with ASSERT_WITH_SECURITY_IMPLICATION before casting to CSSPrimitiveValue*.

  • css/CSSValuePool.h:

(WebCore::CSSValuePool::createValue): A new overload that delegates to the new CSSPrimitiveValue(length,style) constructor.

  • platform/CalculationValue.h:

(WebCore::CalculationValue::operator==):
(WebCore::CalculationValue::isNonNegative):
(WebCore::CalculationValue::expression):
(WebCore::CalcExpressionNumber::value):
(WebCore::toCalcExpressionNumber):
(WebCore::CalcExpressionLength::CalcExpressionLength):
(WebCore::CalcExpressionLength::length):
(WebCore::toCalcExpressionLength):
(WebCore::CalcExpressionBinaryOperation::leftSide):
(WebCore::CalcExpressionBinaryOperation::rightSide):
(WebCore::CalcExpressionBinaryOperation::getOperator):
(WebCore::toCalcExpressionBinaryOperation):
(WebCore::CalcExpressionBlendLength::CalcExpressionBlendLength):
(WebCore::CalcExpressionBlendLength::from):
(WebCore::CalcExpressionBlendLength::to):
(WebCore::CalcExpressionBlendLength::progress):
(WebCore::toCalcExpressionBlendLength):

LayoutTests:

Specifying a CSS Shape geometry Length attribute with a calc() expression
or looking up the value with getComputedStyle(), caused crashes.

  • fast/shapes/shape-inside/shape-inside-calc-crash-expected.txt: Added.
  • fast/shapes/shape-inside/shape-inside-calc-crash.html: Added.
  • css3/calc/simplification-expected.txt: Added
  • css3/calc/simplification.html: Added
  • LayoutTests/css3/calc/cssom-expected.txt:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/css/CSSCalculationValue.h

    r156260 r156586  
    3333
    3434#include "CSSParserValues.h"
     35#include "CSSPrimitiveValue.h"
    3536#include "CSSValue.h"
    3637#include "CalculationValue.h"
     
    4344class CSSParserValueList;
    4445class CSSValueList;
    45 class RenderStyle;
    4646class CalculationValue;
    4747class CalcExpressionNode;
     48class RenderStyle;
     49struct Length;
    4850
    4951enum CalculationCategory {
     
    5860    CalcOther
    5961};
    60    
     62
    6163class CSSCalcExpressionNode : public RefCounted<CSSCalcExpressionNode> {
    6264public:
     
    6870    virtual ~CSSCalcExpressionNode() = 0;
    6971    virtual bool isZero() const = 0;
    70     virtual PassOwnPtr<CalcExpressionNode> toCalcValue(const RenderStyle*, const RenderStyle* rootStyle, double zoom = 1.0) const = 0;   
     72    virtual PassOwnPtr<CalcExpressionNode> toCalcValue(const RenderStyle*, const RenderStyle* rootStyle, double zoom = 1.0) const = 0;
    7173    virtual double doubleValue() const = 0;
    7274    virtual double computeLengthPx(const RenderStyle* currentStyle, const RenderStyle* rootStyle, double multiplier = 1.0, bool computingFontSize = false) const = 0;
     
    7981    virtual Type type() const = 0;
    8082
    81     CalculationCategory category() const { return m_category; }   
     83    CalculationCategory category() const { return m_category; }
     84    virtual CSSPrimitiveValue::UnitTypes primitiveType() const = 0;
    8285    bool isInteger() const { return m_isInteger; }
    83    
     86
    8487protected:
    8588    CSSCalcExpressionNode(CalculationCategory category, bool isInteger)
     
    8891    {
    8992    }
    90    
     93
    9194    CalculationCategory m_category;
    9295    bool m_isInteger;
    9396};
    94        
     97
    9598class CSSCalcValue : public CSSValue {
    9699public:
    97100    static PassRefPtr<CSSCalcValue> create(CSSParserString name, CSSParserValueList*, CalculationPermittedValueRange);
    98     static PassRefPtr<CSSCalcValue> create(CalculationValue*);
     101    static PassRefPtr<CSSCalcValue> create(PassRefPtr<CSSCalcExpressionNode>, CalculationPermittedValueRange = CalculationRangeAll);
     102    static PassRefPtr<CSSCalcValue> create(const CalculationValue* value, const RenderStyle* style) { return adoptRef(new CSSCalcValue(value, style)); }
     103
     104    static PassRefPtr<CSSCalcExpressionNode> createExpressionNode(PassRefPtr<CSSPrimitiveValue>, bool isInteger = false);
     105    static PassRefPtr<CSSCalcExpressionNode> createExpressionNode(PassRefPtr<CSSCalcExpressionNode>, PassRefPtr<CSSCalcExpressionNode>, CalcOperator);
     106    static PassRefPtr<CSSCalcExpressionNode> createExpressionNode(const CalcExpressionNode*, const RenderStyle*);
     107    static PassRefPtr<CSSCalcExpressionNode> createExpressionNode(const Length&, const RenderStyle*);
    99108
    100109    PassRefPtr<CalculationValue> toCalcValue(const RenderStyle* style, const RenderStyle* rootStyle, double zoom = 1.0) const
     
    103112    }
    104113    CalculationCategory category() const { return m_expression->category(); }
    105     bool isInt() const { return m_expression->isInteger(); }   
     114    bool isInt() const { return m_expression->isInteger(); }
    106115    double doubleValue() const;
    107116    bool isNegative() const { return m_expression->doubleValue() < 0; }
     117    CalculationPermittedValueRange permittedValueRange() { return m_nonNegative ? CalculationRangeNonNegative : CalculationRangeAll; }
    108118    double computeLengthPx(const RenderStyle* currentStyle, const RenderStyle* rootStyle, double multiplier = 1.0, bool computingFontSize = false) const;
    109        
     119    CSSCalcExpressionNode* expressionNode() const { return m_expression.get(); }
     120
    110121    String customCSSText() const;
    111122    bool equals(const CSSCalcValue&) const;
     
    114125    bool hasVariableReference() const;
    115126#endif
    116    
    117 private:   
     127
     128private:
    118129    CSSCalcValue(PassRefPtr<CSSCalcExpressionNode> expression, CalculationPermittedValueRange range)
    119130        : CSSValue(CalculationClass)
     
    122133    {
    123134    }
    124    
     135    CSSCalcValue(const CalculationValue* value, const RenderStyle* style)
     136        : CSSValue(CalculationClass)
     137        , m_expression(createExpressionNode(value->expression(), style))
     138        , m_nonNegative(value->isNonNegative())
     139    {
     140    }
     141
    125142    double clampToPermittedRange(double) const;
    126143
     
    128145    const bool m_nonNegative;
    129146};
    130    
     147
     148inline CSSCalcValue* toCSSCalcValue(CSSValue* value)
     149{
     150    ASSERT_WITH_SECURITY_IMPLICATION(!value || value->isCalculationValue());
     151    return static_cast<CSSCalcValue*>(value);
     152}
     153
     154inline const CSSCalcValue* toCSSCalcValue(const CSSValue* value)
     155{
     156    ASSERT_WITH_SECURITY_IMPLICATION(!value || value->isCalculationValue());
     157    return static_cast<const CSSCalcValue*>(value);
     158}
     159
    131160} // namespace WebCore
    132161
Note: See TracChangeset for help on using the changeset viewer.