Bug 1272475 - Part 1: Clamp max/min float value in the parser of CSS Transform function. draft
authorBoris Chiou <boris.chiou@gmail.com>
Wed, 20 Jul 2016 15:14:05 +0800
changeset 390584 3e09180340258707c4795f3aba92f454dcd0d504
parent 386893 04821a70c739a00d12e12df651c0989441e22728
child 390585 a0b4991066e98c3e0b84a60b20ec7d8bfccc9251
push id23696
push userbmo:boris.chiou@gmail.com
push dateThu, 21 Jul 2016 11:17:11 +0000
bugs1272475
milestone50.0a1
Bug 1272475 - Part 1: Clamp max/min float value in the parser of CSS Transform function. To avoid calculate +/-infinite function value, we clamp it in the parser level. Also, we use EnsureNotNan while calculating the interpolation for translate function, so it's also better to do EnsureNotNan before call SetFloatValue() while calculating the interpolation for rotate (AddCSSValueAngle) and scale functions. MozReview-Commit-ID: 1k19ytyNG1N
layout/style/StyleAnimationValue.cpp
layout/style/nsCSSParser.cpp
--- a/layout/style/StyleAnimationValue.cpp
+++ b/layout/style/StyleAnimationValue.cpp
@@ -1077,23 +1077,25 @@ AddCSSValueCanonicalCalc(double aCoeff1,
 
 static void
 AddCSSValueAngle(double aCoeff1, const nsCSSValue &aValue1,
                  double aCoeff2, const nsCSSValue &aValue2,
                  nsCSSValue &aResult)
 {
   if (aValue1.GetUnit() == aValue2.GetUnit()) {
     // To avoid floating point error, if the units match, maintain the unit.
-    aResult.SetFloatValue(aCoeff1 * aValue1.GetFloatValue() +
-                          aCoeff2 * aValue2.GetFloatValue(),
-                          aValue1.GetUnit());
+    aResult.SetFloatValue(
+      EnsureNotNan(aCoeff1 * aValue1.GetFloatValue() +
+                   aCoeff2 * aValue2.GetFloatValue()),
+      aValue1.GetUnit());
   } else {
-    aResult.SetFloatValue(aCoeff1 * aValue1.GetAngleValueInRadians() +
-                          aCoeff2 * aValue2.GetAngleValueInRadians(),
-                          eCSSUnit_Radian);
+    aResult.SetFloatValue(
+      EnsureNotNan(aCoeff1 * aValue1.GetAngleValueInRadians() +
+                   aCoeff2 * aValue2.GetAngleValueInRadians()),
+      eCSSUnit_Radian);
   }
 }
 
 static bool
 AddCSSValuePixelPercentCalc(const uint32_t aValueRestrictions,
                             const nsCSSUnit aCommonUnit,
                             double aCoeff1, const nsCSSValue &aValue1,
                             double aCoeff2, const nsCSSValue &aValue2,
@@ -1249,17 +1251,17 @@ AddTransformScale(double aCoeff1, const 
   // back.  This gets the right AddWeighted behavior and gets us the
   // interpolation-against-identity behavior for free.
   MOZ_ASSERT(aValue1.GetUnit() == eCSSUnit_Number, "unexpected unit");
   MOZ_ASSERT(aValue2.GetUnit() == eCSSUnit_Number, "unexpected unit");
 
   float v1 = aValue1.GetFloatValue() - 1.0f,
         v2 = aValue2.GetFloatValue() - 1.0f;
   float result = v1 * aCoeff1 + v2 * aCoeff2;
-  aResult.SetFloatValue(result + 1.0f, eCSSUnit_Number);
+  aResult.SetFloatValue(EnsureNotNan(result + 1.0f), eCSSUnit_Number);
 }
 
 /* static */ already_AddRefed<nsCSSValue::Array>
 StyleAnimationValue::AppendTransformFunction(nsCSSKeyword aTransformFunction,
                                              nsCSSValueList**& aListTail)
 {
   RefPtr<nsCSSValue::Array> arr = AppendFunction(aTransformFunction);
   nsCSSValueList *item = new nsCSSValueList;
--- a/layout/style/nsCSSParser.cpp
+++ b/layout/style/nsCSSParser.cpp
@@ -15412,16 +15412,26 @@ CSSParserImpl::ParseFunctionInternals(co
 
   for (uint16_t index = 0; index < aMaxElems; ++index) {
     nsCSSValue newValue;
     uint32_t m = aVariantMaskAll ? aVariantMaskAll : aVariantMask[index];
     if (ParseVariant(newValue, m, nullptr) != CSSParseResult::Ok) {
       break;
     }
 
+    if (newValue.GetUnit() >= eCSSUnit_Number) {
+      // Clamp infinity or -infinity values to max float or -max float to avoid
+      // calculations with infinity.
+      newValue.SetFloatValue(
+        mozilla::clamped(newValue.GetFloatValue(),
+                         -std::numeric_limits<float>::max(),
+                          std::numeric_limits<float>::max()),
+        newValue.GetUnit());
+    }
+
     aOutput.AppendElement(newValue);
 
     if (ExpectSymbol(',', true)) {
       // Move on to the next argument if we see a comma.
       continue;
     }
 
     if (ExpectSymbol(')', true)) {