Commit 66a95ed7 authored by alancutter's avatar alancutter Committed by Commit bot

Prevent floating point overflow when using calc() with large values

BUG=676286

Review-Url: https://codereview.chromium.org/2597103002
Cr-Commit-Position: refs/heads/master@{#441339}
parent 4f7b28c2
<script src="../../resources/testharness.js"></script>
<script src="../../resources/testharnessreport.js"></script>
<body></body>
<script>
function undefinedBehaviourTest(input, expected, type) {
test(() => {
var target = document.createElement('div');
document.body.appendChild(target);
target.style.lineHeight = input;
assert_equals(getComputedStyle(target).lineHeight, expected);
target.remove();
}, 'Do not invoke undefined behaviour when using calc()s with large ' + type + ' values');
}
undefinedBehaviourTest('calc(1e400px * 1e400)', '3.35544e+07px', 'pixel');
undefinedBehaviourTest('calc(1e400% * 1e400)', '3.43597e+08px', 'percentage');
</script>
......@@ -185,19 +185,22 @@ class CSSCalcPrimitiveValue final : public CSSCalcExpressionNode {
float multiplier) const override {
switch (m_category) {
case CalcLength:
value.pixels +=
m_value->computeLength<float>(conversionData) * multiplier;
value.pixels = clampTo<float>(
value.pixels +
m_value->computeLength<double>(conversionData) * multiplier);
break;
case CalcPercent:
ASSERT(m_value->isPercentage());
value.percent += m_value->getDoubleValue() * multiplier;
value.percent = clampTo<float>(value.percent +
m_value->getDoubleValue() * multiplier);
break;
case CalcNumber:
// TODO(alancutter): Stop treating numbers like pixels unconditionally
// in calcs to be able to accomodate border-image-width
// https://drafts.csswg.org/css-backgrounds-3/#the-border-image-width
value.pixels +=
m_value->getDoubleValue() * conversionData.zoom() * multiplier;
value.pixels = clampTo<float>(value.pixels +
m_value->getDoubleValue() *
conversionData.zoom() * multiplier);
break;
default:
ASSERT_NOT_REACHED();
......@@ -396,14 +399,14 @@ class CSSCalcBinaryOperation final : public CSSCalcExpressionNode {
CSSPrimitiveValue::canonicalUnitTypeForCategory(
leftUnitCategory);
if (canonicalType != CSSPrimitiveValue::UnitType::Unknown) {
double leftValue =
double leftValue = clampTo<double>(
leftSide->doubleValue() *
CSSPrimitiveValue::conversionToCanonicalUnitsScaleFactor(
leftType);
double rightValue =
leftType));
double rightValue = clampTo<double>(
rightSide->doubleValue() *
CSSPrimitiveValue::conversionToCanonicalUnitsScaleFactor(
rightType);
rightType));
return CSSCalcPrimitiveValue::create(
evaluateOperator(leftValue, rightValue, op), canonicalType,
isInteger);
......@@ -623,14 +626,14 @@ class CSSCalcBinaryOperation final : public CSSCalcExpressionNode {
CalcOperator op) {
switch (op) {
case CalcAdd:
return leftValue + rightValue;
return clampTo<double>(leftValue + rightValue);
case CalcSubtract:
return leftValue - rightValue;
return clampTo<double>(leftValue - rightValue);
case CalcMultiply:
return leftValue * rightValue;
return clampTo<double>(leftValue * rightValue);
case CalcDivide:
if (rightValue)
return leftValue / rightValue;
return clampTo<double>(leftValue / rightValue);
return std::numeric_limits<double>::quiet_NaN();
}
return 0;
......
......@@ -850,8 +850,10 @@ Length StyleBuilderConverter::convertLineHeight(StyleResolverState& state,
100.0,
Fixed);
}
if (primitiveValue.isNumber())
return Length(primitiveValue.getDoubleValue() * 100.0, Percent);
if (primitiveValue.isNumber()) {
return Length(clampTo<float>(primitiveValue.getDoubleValue() * 100.0),
Percent);
}
if (primitiveValue.isCalculated()) {
Length zoomedLength = Length(primitiveValue.cssCalcValue()->toCalcValue(
lineHeightToLengthConversionData(state)));
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment