Bug 1324693 - Make parse_dimension() return a finite value. draft
authorBoris Chiou <boris.chiou@gmail.com>
Mon, 27 Mar 2017 16:02:44 +0800
changeset 551679 f8018a809998c175796be67ef4ef2dd6ee8a184a
parent 504632 4c987b7ed54a630a7de76adcc2eb00dab49d5dfd
child 551680 53f33cb7d166be91b6dd39862ba2018604507757
push id51132
push userbmo:boris.chiou@gmail.com
push dateMon, 27 Mar 2017 08:40:57 +0000
bugs1324693
milestone55.0a1
Bug 1324693 - Make parse_dimension() return a finite value. We use parse_dimension() to parse specified::Angle, and it is possible to input an extra large angle, e.g. rotate(9.5e+307rad), so we need to clamp it to avoid any assertion in Gecko. MozReview-Commit-ID: 46afm6lUe16
servo/components/style/values/specified/mod.rs
--- a/servo/components/style/values/specified/mod.rs
+++ b/servo/components/style/values/specified/mod.rs
@@ -214,28 +214,31 @@ pub fn parse_integer(input: &mut Parser)
                 _ => Err(())
             }
         }
         _ => Err(())
     }
 }
 
 #[allow(missing_docs)]
+fn clamp_f32(value: f32) -> f32 {
+    use std::f32;
+    if value.is_finite() {
+        value
+    } else if value.is_sign_positive() {
+        f32::MAX
+    } else {
+        f32::MIN
+    }
+}
+
+#[allow(missing_docs)]
 pub fn parse_number(input: &mut Parser) -> Result<f32, ()> {
     match try!(input.next()) {
-        Token::Number(ref value) => {
-            use std::f32;
-            if value.value.is_finite() {
-                Ok(value.value)
-            } else if value.value.is_sign_positive() {
-                Ok(f32::MAX)
-            } else {
-                Ok(f32::MIN)
-            }
-        },
+        Token::Number(ref value) => Ok(clamp_f32(value.value)),
         Token::Function(ref name) if name.eq_ignore_ascii_case("calc") => {
             let ast = try!(input.parse_nested_block(|i| CalcLengthOrPercentage::parse_sum(i, CalcUnit::Number)));
 
             let mut result = None;
 
             for ref node in ast.products {
                 match try!(CalcLengthOrPercentage::simplify_product(node)) {
                     SimplifiedValueNode::Number(val) =>
@@ -337,20 +340,27 @@ impl Parse for Angle {
             _ => Err(())
         }
     }
 }
 
 impl Angle {
     #[allow(missing_docs)]
     pub fn parse_dimension(value: CSSFloat, unit: &str) -> Result<Angle, ()> {
+        if value.is_infinite() {
+            return Ok(Angle(clamp_f32(value)))
+        }
+
         match_ignore_ascii_case! { unit,
             "deg" => Ok(Angle(value * RAD_PER_DEG)),
             "grad" => Ok(Angle(value * RAD_PER_GRAD)),
-            "turn" => Ok(Angle(value * RAD_PER_TURN)),
+            "turn" => {
+                // RAD_PER_TURN is 2.0 (large than 1.0), so |value * RAD_PER_TURN| might be inf.
+                Ok(Angle(clamp_f32(value * RAD_PER_TURN)))
+            },
             "rad" => Ok(Angle(value)),
              _ => Err(())
         }
     }
 }
 
 #[allow(missing_docs)]
 pub fn parse_border_radius(context: &ParserContext, input: &mut Parser) -> Result<BorderRadiusSize, ()> {