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
--- 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, ()> {