Index: Source/core/css/CSSCalculationValue.cpp |
diff --git a/Source/core/css/CSSCalculationValue.cpp b/Source/core/css/CSSCalculationValue.cpp |
index f63358a8f0645e3dddffe28bbab474c5c5e03501..08b276ce336fca5a3da5fb7f1b2badd66c72ec9a 100644 |
--- a/Source/core/css/CSSCalculationValue.cpp |
+++ b/Source/core/css/CSSCalculationValue.cpp |
@@ -591,26 +591,25 @@ private: |
const CalcOperator m_operator; |
}; |
-static ParseState checkDepthAndIndex(int* depth, unsigned index, CSSParserValueList* tokens) |
+static ParseState checkDepthAndIndex(int* depth, CSSParserTokenRange tokens) |
{ |
(*depth)++; |
+ if (tokens.atEnd()) |
+ return NoMoreTokens; |
if (*depth > maxExpressionDepth) |
return TooDeep; |
- if (index >= tokens->size()) |
- return NoMoreTokens; |
return OK; |
} |
class CSSCalcExpressionNodeParser { |
STACK_ALLOCATED(); |
public: |
- PassRefPtrWillBeRawPtr<CSSCalcExpressionNode> parseCalc(CSSParserValueList* tokens) |
+ PassRefPtrWillBeRawPtr<CSSCalcExpressionNode> parseCalc(CSSParserTokenRange tokens) |
{ |
- unsigned index = 0; |
Value result; |
- bool ok = parseValueExpression(tokens, 0, &index, &result); |
- ASSERT_WITH_SECURITY_IMPLICATION(index <= tokens->size()); |
- if (!ok || index != tokens->size()) |
+ tokens.consumeWhitespace(); |
+ bool ok = parseValueExpression(tokens, 0, &result); |
+ if (!ok || !tokens.atEnd()) |
return nullptr; |
return result.value; |
} |
@@ -622,69 +621,59 @@ private: |
RefPtrWillBeMember<CSSCalcExpressionNode> value; |
}; |
- char operatorValue(CSSParserValueList* tokens, unsigned index) |
+ char operatorValue(const CSSParserToken& token) |
{ |
- if (index >= tokens->size()) |
- return 0; |
- CSSParserValue* value = tokens->valueAt(index); |
- if (value->m_unit != CSSParserValue::Operator) |
- return 0; |
- |
- return value->iValue; |
+ if (token.type() == DelimiterToken) |
+ return token.delimiter(); |
+ return 0; |
} |
- bool parseValue(CSSParserValueList* tokens, unsigned* index, Value* result) |
+ bool parseValue(CSSParserTokenRange& tokens, Value* result) |
{ |
- CSSParserValue* parserValue = tokens->valueAt(*index); |
- if (parserValue->m_unit >= CSSParserValue::Operator) |
+ CSSParserToken token = tokens.consumeIncludingWhitespace(); |
+ if (!(token.type() == NumberToken || token.type() == PercentageToken || token.type() == DimensionToken)) |
return false; |
- CSSPrimitiveValue::UnitType type = parserValue->unit(); |
+ CSSPrimitiveValue::UnitType type = token.unitType(); |
if (unitCategory(type) == CalcOther) |
return false; |
result->value = CSSCalcPrimitiveValue::create( |
- CSSPrimitiveValue::create(parserValue->fValue, type), parserValue->isInt); |
+ CSSPrimitiveValue::create(token.numericValue(), type), token.numericValueType() == IntegerValueType); |
- ++*index; |
return true; |
} |
- bool parseValueTerm(CSSParserValueList* tokens, int depth, unsigned* index, Value* result) |
+ bool parseValueTerm(CSSParserTokenRange& tokens, int depth, Value* result) |
{ |
- if (checkDepthAndIndex(&depth, *index, tokens) != OK) |
+ if (checkDepthAndIndex(&depth, tokens) != OK) |
return false; |
- if (operatorValue(tokens, *index) == '(') { |
- unsigned currentIndex = *index + 1; |
- if (!parseValueExpression(tokens, depth, ¤tIndex, result)) |
- return false; |
- |
- if (operatorValue(tokens, currentIndex) != ')') |
- return false; |
- *index = currentIndex + 1; |
- return true; |
+ if (tokens.peek().type() == LeftParenthesisToken) { |
+ CSSParserTokenRange innerRange = tokens.consumeBlock(); |
+ tokens.consumeWhitespace(); |
+ return parseValueExpression(innerRange, depth, result); |
} |
- return parseValue(tokens, index, result); |
+ return parseValue(tokens, result); |
} |
- bool parseValueMultiplicativeExpression(CSSParserValueList* tokens, int depth, unsigned* index, Value* result) |
+ bool parseValueMultiplicativeExpression(CSSParserTokenRange& tokens, int depth, Value* result) |
{ |
- if (checkDepthAndIndex(&depth, *index, tokens) != OK) |
+ if (checkDepthAndIndex(&depth, tokens) != OK) |
return false; |
- if (!parseValueTerm(tokens, depth, index, result)) |
+ if (!parseValueTerm(tokens, depth, result)) |
return false; |
- while (*index < tokens->size() - 1) { |
- char operatorCharacter = operatorValue(tokens, *index); |
+ while (!tokens.atEnd()) { |
+ char operatorCharacter = operatorValue(tokens.peek()); |
if (operatorCharacter != CalcMultiply && operatorCharacter != CalcDivide) |
break; |
- ++*index; |
+ tokens.consumeIncludingWhitespace(); |
Value rhs; |
- if (!parseValueTerm(tokens, depth, index, &rhs)) |
+ if (!parseValueTerm(tokens, depth, &rhs)) |
return false; |
result->value = CSSCalcBinaryOperation::createSimplified(result->value, rhs.value, static_cast<CalcOperator>(operatorCharacter)); |
@@ -692,26 +681,30 @@ private: |
return false; |
} |
- ASSERT_WITH_SECURITY_IMPLICATION(*index <= tokens->size()); |
return true; |
} |
- bool parseAdditiveValueExpression(CSSParserValueList* tokens, int depth, unsigned* index, Value* result) |
+ bool parseAdditiveValueExpression(CSSParserTokenRange& tokens, int depth, Value* result) |
{ |
- if (checkDepthAndIndex(&depth, *index, tokens) != OK) |
+ if (checkDepthAndIndex(&depth, tokens) != OK) |
return false; |
- if (!parseValueMultiplicativeExpression(tokens, depth, index, result)) |
+ if (!parseValueMultiplicativeExpression(tokens, depth, result)) |
return false; |
- while (*index < tokens->size() - 1) { |
- char operatorCharacter = operatorValue(tokens, *index); |
+ while (!tokens.atEnd()) { |
+ char operatorCharacter = operatorValue(tokens.peek()); |
if (operatorCharacter != CalcAdd && operatorCharacter != CalcSubtract) |
break; |
- ++*index; |
+ if ((&tokens.peek() - 1)->type() != WhitespaceToken) |
+ return false; // calc(1px+ 2px) is invalid |
+ tokens.consume(); |
+ if (tokens.peek().type() != WhitespaceToken) |
+ return false; // calc(1px +2px) is invalid |
+ tokens.consumeIncludingWhitespace(); |
Value rhs; |
- if (!parseValueMultiplicativeExpression(tokens, depth, index, &rhs)) |
+ if (!parseValueMultiplicativeExpression(tokens, depth, &rhs)) |
return false; |
result->value = CSSCalcBinaryOperation::createSimplified(result->value, rhs.value, static_cast<CalcOperator>(operatorCharacter)); |
@@ -719,13 +712,12 @@ private: |
return false; |
} |
- ASSERT_WITH_SECURITY_IMPLICATION(*index <= tokens->size()); |
return true; |
} |
- bool parseValueExpression(CSSParserValueList* tokens, int depth, unsigned* index, Value* result) |
+ bool parseValueExpression(CSSParserTokenRange& tokens, int depth, Value* result) |
{ |
- return parseAdditiveValueExpression(tokens, depth, index, result); |
+ return parseAdditiveValueExpression(tokens, depth, result); |
} |
}; |
@@ -747,10 +739,10 @@ PassRefPtrWillBeRawPtr<CSSCalcExpressionNode> CSSCalcValue::createExpressionNode |
CalcAdd); |
} |
-PassRefPtrWillBeRawPtr<CSSCalcValue> CSSCalcValue::create(CSSParserValueList* parserValueList, ValueRange range) |
+PassRefPtrWillBeRawPtr<CSSCalcValue> CSSCalcValue::create(const CSSParserTokenRange& tokens, ValueRange range) |
{ |
CSSCalcExpressionNodeParser parser; |
- RefPtrWillBeRawPtr<CSSCalcExpressionNode> expression = parser.parseCalc(parserValueList); |
+ RefPtrWillBeRawPtr<CSSCalcExpressionNode> expression = parser.parseCalc(tokens); |
return expression ? adoptRefWillBeNoop(new CSSCalcValue(expression, range)) : nullptr; |
} |