Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright (C) 2011, 2012 Google Inc. All rights reserved. | 2 * Copyright (C) 2011, 2012 Google Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
| 6 * met: | 6 * met: |
| 7 * | 7 * |
| 8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
| 9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
| 10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
| (...skipping 574 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 585 return std::numeric_limits<double>::quiet_NaN(); | 585 return std::numeric_limits<double>::quiet_NaN(); |
| 586 } | 586 } |
| 587 return 0; | 587 return 0; |
| 588 } | 588 } |
| 589 | 589 |
| 590 const RefPtrWillBeMember<CSSCalcExpressionNode> m_leftSide; | 590 const RefPtrWillBeMember<CSSCalcExpressionNode> m_leftSide; |
| 591 const RefPtrWillBeMember<CSSCalcExpressionNode> m_rightSide; | 591 const RefPtrWillBeMember<CSSCalcExpressionNode> m_rightSide; |
| 592 const CalcOperator m_operator; | 592 const CalcOperator m_operator; |
| 593 }; | 593 }; |
| 594 | 594 |
| 595 static ParseState checkDepthAndIndex(int* depth, unsigned index, CSSParserValueL ist* tokens) | 595 static ParseState checkDepthAndIndex(int* depth, CSSParserTokenRange tokens) |
| 596 { | 596 { |
| 597 (*depth)++; | 597 (*depth)++; |
| 598 if (tokens.atEnd()) | |
| 599 return NoMoreTokens; | |
| 598 if (*depth > maxExpressionDepth) | 600 if (*depth > maxExpressionDepth) |
| 599 return TooDeep; | 601 return TooDeep; |
| 600 if (index >= tokens->size()) | |
| 601 return NoMoreTokens; | |
| 602 return OK; | 602 return OK; |
| 603 } | 603 } |
| 604 | 604 |
| 605 class CSSCalcExpressionNodeParser { | 605 class CSSCalcExpressionNodeParser { |
| 606 STACK_ALLOCATED(); | 606 STACK_ALLOCATED(); |
| 607 public: | 607 public: |
| 608 PassRefPtrWillBeRawPtr<CSSCalcExpressionNode> parseCalc(CSSParserValueList* tokens) | 608 PassRefPtrWillBeRawPtr<CSSCalcExpressionNode> parseCalc(CSSParserTokenRange tokens) |
| 609 { | 609 { |
| 610 unsigned index = 0; | |
| 611 Value result; | 610 Value result; |
| 612 bool ok = parseValueExpression(tokens, 0, &index, &result); | 611 bool ok = parseValueExpression(tokens, 0, &result); |
| 613 ASSERT_WITH_SECURITY_IMPLICATION(index <= tokens->size()); | 612 if (!ok || !tokens.atEnd()) |
| 614 if (!ok || index != tokens->size()) | |
| 615 return nullptr; | 613 return nullptr; |
| 616 return result.value; | 614 return result.value; |
| 617 } | 615 } |
| 618 | 616 |
| 619 private: | 617 private: |
| 620 struct Value { | 618 struct Value { |
| 621 STACK_ALLOCATED(); | 619 STACK_ALLOCATED(); |
| 622 public: | 620 public: |
| 623 RefPtrWillBeMember<CSSCalcExpressionNode> value; | 621 RefPtrWillBeMember<CSSCalcExpressionNode> value; |
| 624 }; | 622 }; |
| 625 | 623 |
| 626 char operatorValue(CSSParserValueList* tokens, unsigned index) | 624 char operatorValue(CSSParserTokenRange& tokens) |
|
Timothy Loh
2015/07/21 07:33:17
I don't think this function helps, or at least it
rwlbuis
2015/07/22 02:19:06
Perhaps. I did not want to change the original cod
Timothy Loh
2015/07/28 08:17:40
I think this function makes it hard to verify that
| |
| 627 { | 625 { |
| 628 if (index >= tokens->size()) | 626 tokens.consumeWhitespace(); |
| 629 return 0; | 627 // Use peek since we do not want to consume in case |
| 630 CSSParserValue* value = tokens->valueAt(index); | 628 // the operator is not the expected mult/add operation. |
| 631 if (value->unit != CSSParserValue::Operator) | 629 CSSParserToken value = tokens.peek(); |
| 632 return 0; | 630 if (value.type() == DelimiterToken) |
| 633 | 631 return value.delimiter(); |
| 634 return value->iValue; | 632 if (value.type() == LeftParenthesisToken) |
| 633 return '('; | |
| 634 if (value.type() == RightParenthesisToken) | |
| 635 return ')'; | |
| 636 return 0; | |
| 635 } | 637 } |
| 636 | 638 |
| 637 bool parseValue(CSSParserValueList* tokens, unsigned* index, Value* result) | 639 bool parseValue(CSSParserTokenRange& tokens, Value* result) |
| 638 { | 640 { |
| 639 CSSParserValue* parserValue = tokens->valueAt(*index); | 641 CSSParserToken token = tokens.consumeSkippingWhitespace(); |
| 640 if (parserValue->unit >= CSSParserValue::Operator) | 642 CSSPrimitiveValue::UnitType type = token.unitType(); |
|
alancutter (OOO until 2018)
2015/07/21 07:44:26
This line should stay after the token.type() check
rwlbuis
2015/07/21 21:29:52
Done.
| |
| 643 if (!(token.type() == NumberToken || token.type() == PercentageToken || token.type() == DimensionToken)) | |
| 641 return false; | 644 return false; |
| 642 | 645 |
| 643 CSSPrimitiveValue::UnitType type = static_cast<CSSPrimitiveValue::UnitTy pe>(parserValue->unit); | |
| 644 if (unitCategory(type) == CalcOther) | 646 if (unitCategory(type) == CalcOther) |
| 645 return false; | 647 return false; |
| 646 | 648 |
| 647 result->value = CSSCalcPrimitiveValue::create( | 649 result->value = CSSCalcPrimitiveValue::create( |
| 648 CSSPrimitiveValue::create(parserValue->fValue, type), parserValue->i sInt); | 650 CSSPrimitiveValue::create(token.numericValue(), type), token.numeric ValueType() == IntegerValueType); |
| 649 | 651 |
| 650 ++*index; | |
| 651 return true; | 652 return true; |
| 652 } | 653 } |
| 653 | 654 |
| 654 bool parseValueTerm(CSSParserValueList* tokens, int depth, unsigned* index, Value* result) | 655 bool parseValueTerm(CSSParserTokenRange& tokens, int depth, Value* result) |
| 655 { | 656 { |
| 656 if (checkDepthAndIndex(&depth, *index, tokens) != OK) | 657 if (checkDepthAndIndex(&depth, tokens) != OK) |
| 657 return false; | 658 return false; |
| 658 | 659 |
| 659 if (operatorValue(tokens, *index) == '(') { | 660 if (operatorValue(tokens) == '(') { |
| 660 unsigned currentIndex = *index + 1; | 661 tokens.consume(); |
| 661 if (!parseValueExpression(tokens, depth, ¤tIndex, result)) | 662 if (!parseValueExpression(tokens, depth, result)) |
| 662 return false; | 663 return false; |
| 663 | 664 |
| 664 if (operatorValue(tokens, currentIndex) != ')') | 665 if (operatorValue(tokens) != ')') |
| 665 return false; | 666 return false; |
| 666 *index = currentIndex + 1; | 667 tokens.consume(); |
| 667 return true; | 668 return true; |
| 668 } | 669 } |
| 669 | 670 |
| 670 return parseValue(tokens, index, result); | 671 return parseValue(tokens, result); |
| 671 } | 672 } |
| 672 | 673 |
| 673 bool parseValueMultiplicativeExpression(CSSParserValueList* tokens, int dept h, unsigned* index, Value* result) | 674 bool parseValueMultiplicativeExpression(CSSParserTokenRange& tokens, int dep th, Value* result) |
| 674 { | 675 { |
| 675 if (checkDepthAndIndex(&depth, *index, tokens) != OK) | 676 if (checkDepthAndIndex(&depth, tokens) != OK) |
| 676 return false; | 677 return false; |
| 677 | 678 |
| 678 if (!parseValueTerm(tokens, depth, index, result)) | 679 if (!parseValueTerm(tokens, depth, result)) |
| 679 return false; | 680 return false; |
| 680 | 681 |
| 681 while (*index < tokens->size() - 1) { | 682 while (!tokens.atEnd()) { |
| 682 char operatorCharacter = operatorValue(tokens, *index); | 683 char operatorCharacter = operatorValue(tokens); |
| 683 if (operatorCharacter != CalcMultiply && operatorCharacter != CalcDi vide) | 684 if (operatorCharacter != CalcMultiply && operatorCharacter != CalcDi vide) |
| 684 break; | 685 break; |
| 685 ++*index; | 686 tokens.consume(); |
| 686 | 687 |
| 687 Value rhs; | 688 Value rhs; |
| 688 if (!parseValueTerm(tokens, depth, index, &rhs)) | 689 if (!parseValueTerm(tokens, depth, &rhs)) |
| 689 return false; | 690 return false; |
| 690 | 691 |
| 691 result->value = CSSCalcBinaryOperation::createSimplified(result->val ue, rhs.value, static_cast<CalcOperator>(operatorCharacter)); | 692 result->value = CSSCalcBinaryOperation::createSimplified(result->val ue, rhs.value, static_cast<CalcOperator>(operatorCharacter)); |
| 692 if (!result->value) | 693 if (!result->value) |
| 693 return false; | 694 return false; |
| 694 } | 695 } |
| 695 | 696 |
| 696 ASSERT_WITH_SECURITY_IMPLICATION(*index <= tokens->size()); | |
| 697 return true; | 697 return true; |
| 698 } | 698 } |
| 699 | 699 |
| 700 bool parseAdditiveValueExpression(CSSParserValueList* tokens, int depth, uns igned* index, Value* result) | 700 bool parseAdditiveValueExpression(CSSParserTokenRange& tokens, int depth, Va lue* result) |
| 701 { | 701 { |
| 702 if (checkDepthAndIndex(&depth, *index, tokens) != OK) | 702 if (checkDepthAndIndex(&depth, tokens) != OK) |
| 703 return false; | 703 return false; |
| 704 | 704 |
| 705 if (!parseValueMultiplicativeExpression(tokens, depth, index, result)) | 705 if (!parseValueMultiplicativeExpression(tokens, depth, result)) |
| 706 return false; | 706 return false; |
| 707 | 707 |
| 708 while (*index < tokens->size() - 1) { | 708 while (!tokens.atEnd()) { |
| 709 char operatorCharacter = operatorValue(tokens, *index); | 709 char operatorCharacter = operatorValue(tokens); |
| 710 if (operatorCharacter != CalcAdd && operatorCharacter != CalcSubtrac t) | 710 if (operatorCharacter != CalcAdd && operatorCharacter != CalcSubtrac t) |
| 711 break; | 711 break; |
| 712 ++*index; | 712 if (operatorCharacter == CalcAdd && (&tokens.peek() - 1)->type() != WhitespaceToken) |
| 713 return false; // calc(1px+ 2px) is invalid | |
|
Timothy Loh
2015/07/21 07:33:17
Probably need to check the other side too, calc(1p
rwlbuis
2015/07/22 02:19:06
I think it works, I found a similar test in calc-e
Timothy Loh
2015/07/28 08:17:40
I didn't see any such tests. You need to check the
| |
| 714 tokens.consume(); | |
| 713 | 715 |
| 714 Value rhs; | 716 Value rhs; |
| 715 if (!parseValueMultiplicativeExpression(tokens, depth, index, &rhs)) | 717 if (!parseValueMultiplicativeExpression(tokens, depth, &rhs)) |
| 716 return false; | 718 return false; |
| 717 | 719 |
| 718 result->value = CSSCalcBinaryOperation::createSimplified(result->val ue, rhs.value, static_cast<CalcOperator>(operatorCharacter)); | 720 result->value = CSSCalcBinaryOperation::createSimplified(result->val ue, rhs.value, static_cast<CalcOperator>(operatorCharacter)); |
| 719 if (!result->value) | 721 if (!result->value) |
| 720 return false; | 722 return false; |
| 721 } | 723 } |
| 722 | 724 |
| 723 ASSERT_WITH_SECURITY_IMPLICATION(*index <= tokens->size()); | |
| 724 return true; | 725 return true; |
| 725 } | 726 } |
| 726 | 727 |
| 727 bool parseValueExpression(CSSParserValueList* tokens, int depth, unsigned* i ndex, Value* result) | 728 bool parseValueExpression(CSSParserTokenRange& tokens, int depth, Value* res ult) |
| 728 { | 729 { |
| 729 return parseAdditiveValueExpression(tokens, depth, index, result); | 730 return parseAdditiveValueExpression(tokens, depth, result); |
| 730 } | 731 } |
| 731 }; | 732 }; |
| 732 | 733 |
| 733 PassRefPtrWillBeRawPtr<CSSCalcExpressionNode> CSSCalcValue::createExpressionNode (PassRefPtrWillBeRawPtr<CSSPrimitiveValue> value, bool isInteger) | 734 PassRefPtrWillBeRawPtr<CSSCalcExpressionNode> CSSCalcValue::createExpressionNode (PassRefPtrWillBeRawPtr<CSSPrimitiveValue> value, bool isInteger) |
| 734 { | 735 { |
| 735 return CSSCalcPrimitiveValue::create(value, isInteger); | 736 return CSSCalcPrimitiveValue::create(value, isInteger); |
| 736 } | 737 } |
| 737 | 738 |
| 738 PassRefPtrWillBeRawPtr<CSSCalcExpressionNode> CSSCalcValue::createExpressionNode (PassRefPtrWillBeRawPtr<CSSCalcExpressionNode> leftSide, PassRefPtrWillBeRawPtr< CSSCalcExpressionNode> rightSide, CalcOperator op) | 739 PassRefPtrWillBeRawPtr<CSSCalcExpressionNode> CSSCalcValue::createExpressionNode (PassRefPtrWillBeRawPtr<CSSCalcExpressionNode> leftSide, PassRefPtrWillBeRawPtr< CSSCalcExpressionNode> rightSide, CalcOperator op) |
| 739 { | 740 { |
| 740 return CSSCalcBinaryOperation::create(leftSide, rightSide, op); | 741 return CSSCalcBinaryOperation::create(leftSide, rightSide, op); |
| 741 } | 742 } |
| 742 | 743 |
| 743 PassRefPtrWillBeRawPtr<CSSCalcExpressionNode> CSSCalcValue::createExpressionNode (double pixels, double percent) | 744 PassRefPtrWillBeRawPtr<CSSCalcExpressionNode> CSSCalcValue::createExpressionNode (double pixels, double percent) |
| 744 { | 745 { |
| 745 return createExpressionNode( | 746 return createExpressionNode( |
| 746 createExpressionNode(CSSPrimitiveValue::create(pixels, CSSPrimitiveValue ::CSS_PX), pixels == trunc(pixels)), | 747 createExpressionNode(CSSPrimitiveValue::create(pixels, CSSPrimitiveValue ::CSS_PX), pixels == trunc(pixels)), |
| 747 createExpressionNode(CSSPrimitiveValue::create(percent, CSSPrimitiveValu e::CSS_PERCENTAGE), percent == trunc(percent)), | 748 createExpressionNode(CSSPrimitiveValue::create(percent, CSSPrimitiveValu e::CSS_PERCENTAGE), percent == trunc(percent)), |
| 748 CalcAdd); | 749 CalcAdd); |
| 749 } | 750 } |
| 750 | 751 |
| 751 PassRefPtrWillBeRawPtr<CSSCalcValue> CSSCalcValue::create(CSSParserValueList* pa rserValueList, ValueRange range) | 752 PassRefPtrWillBeRawPtr<CSSCalcValue> CSSCalcValue::create(const CSSParserTokenRa nge& parserValueList, ValueRange range) |
|
alancutter (OOO until 2018)
2015/07/21 07:44:26
s/parserValueList/tokens/
rwlbuis
2015/07/21 21:29:52
Done.
| |
| 752 { | 753 { |
| 753 CSSCalcExpressionNodeParser parser; | 754 CSSCalcExpressionNodeParser parser; |
| 754 RefPtrWillBeRawPtr<CSSCalcExpressionNode> expression = parser.parseCalc(pars erValueList); | 755 RefPtrWillBeRawPtr<CSSCalcExpressionNode> expression = parser.parseCalc(pars erValueList); |
| 755 | 756 |
| 756 return expression ? adoptRefWillBeNoop(new CSSCalcValue(expression, range)) : nullptr; | 757 return expression ? adoptRefWillBeNoop(new CSSCalcValue(expression, range)) : nullptr; |
| 757 } | 758 } |
| 758 | 759 |
| 759 PassRefPtrWillBeRawPtr<CSSCalcValue> CSSCalcValue::create(PassRefPtrWillBeRawPtr <CSSCalcExpressionNode> expression, ValueRange range) | 760 PassRefPtrWillBeRawPtr<CSSCalcValue> CSSCalcValue::create(PassRefPtrWillBeRawPtr <CSSCalcExpressionNode> expression, ValueRange range) |
| 760 { | 761 { |
| 761 return adoptRefWillBeNoop(new CSSCalcValue(expression, range)); | 762 return adoptRefWillBeNoop(new CSSCalcValue(expression, range)); |
| 762 } | 763 } |
| 763 | 764 |
| 764 DEFINE_TRACE_AFTER_DISPATCH(CSSCalcValue) | 765 DEFINE_TRACE_AFTER_DISPATCH(CSSCalcValue) |
| 765 { | 766 { |
| 766 visitor->trace(m_expression); | 767 visitor->trace(m_expression); |
| 767 CSSValue::traceAfterDispatch(visitor); | 768 CSSValue::traceAfterDispatch(visitor); |
| 768 } | 769 } |
| 769 | 770 |
| 770 } // namespace blink | 771 } // namespace blink |
| OLD | NEW |