From b29230bd76ea30ab42fab724fe72a18c396d5e49 Mon Sep 17 00:00:00 2001 From: tigercosmos Date: Sun, 14 Jan 2018 00:01:47 +0800 Subject: [PATCH] implement range input sanitization --- components/script/dom/bindings/str.rs | 45 ++++++++++++++----- components/script/dom/htmlinputelement.rs | 10 ++++- tests/wpt/metadata/MANIFEST.json | 2 +- .../forms/the-input-element/range-2.html.ini | 2 +- .../forms/the-input-element/range.html.ini | 3 -- .../forms/the-input-element/range.html | 32 +++++++++++++ 6 files changed, 75 insertions(+), 19 deletions(-) diff --git a/components/script/dom/bindings/str.rs b/components/script/dom/bindings/str.rs index eaabc29806ce..4520fd15a6c8 100644 --- a/components/script/dom/bindings/str.rs +++ b/components/script/dom/bindings/str.rs @@ -286,31 +286,37 @@ impl DOMString { /// YYYY must be four or more digits, MM and DD both must be two digits /// https://html.spec.whatwg.org/multipage/#valid-date-string pub fn is_valid_date_string(&self) -> bool { - parse_date_string(&*self.0).is_ok() + parse_date_string(&self.0).is_ok() } /// A valid month string should be "YYYY-MM" /// YYYY must be four or more digits, MM both must be two digits /// https://html.spec.whatwg.org/multipage/#valid-month-string pub fn is_valid_month_string(&self) -> bool { - parse_month_string(&*self.0).is_ok() + parse_month_string(&self.0).is_ok() } /// A valid week string should be like {YYYY}-W{WW}, such as "2017-W52" /// YYYY must be four or more digits, WW both must be two digits /// https://html.spec.whatwg.org/multipage/#valid-week-string pub fn is_valid_week_string(&self) -> bool { - parse_week_string(&*self.0).is_ok() + parse_week_string(&self.0).is_ok() } - /// A valid number is the same as what rust considers to be valid, - /// except for +1., NaN, and Infinity. /// https://html.spec.whatwg.org/multipage/#valid-floating-point-number - pub fn is_valid_number_string(&self) -> bool { - let input = &self.0; - input.parse::().ok().map_or(false, |val| { - !(val.is_infinite() || val.is_nan() || input.ends_with(".") || input.starts_with("+")) - }) + pub fn is_valid_floating_point_number_string(&self) -> bool { + // for the case that `parse_floating_point_number` cannot handle + if self.0.contains(" ") { + return false; + } + parse_floating_point_number(&self.0).is_ok() + } + + /// https://html.spec.whatwg.org/multipage/#best-representation-of-the-number-as-a-floating-point-number + pub fn set_best_representation_of_the_floating_point_number(&mut self) { + if let Ok(val) = parse_floating_point_number(&self.0) { + self.0 = val.to_string(); + } } /// A valid normalized local date and time string should be "{date}T{time}" @@ -617,7 +623,7 @@ fn parse_time_component(value: &str) -> Result<(u32, u32, f32), ()> { Ok((hour_int, minute_int, second_float)) } -// https://html.spec.whatwg.org/multipage/#parse-a-local-date-and-time-string +/// https://html.spec.whatwg.org/multipage/#parse-a-local-date-and-time-string fn parse_local_date_and_time_string(value: &str) -> Result<((u32, u32, u32), (u32, u32, f32)), ()> { // Step 1, 2, 4 let mut iterator = if value.contains('T') { @@ -658,7 +664,7 @@ fn max_day_in_month(year_num: u32, month_num: u32) -> Result { } } -// https://html.spec.whatwg.org/multipage/#week-number-of-the-last-day +/// https://html.spec.whatwg.org/multipage/#week-number-of-the-last-day fn max_week_in_year(year: u32) -> u32 { match Utc.ymd(year as i32, 1, 1).weekday() { Weekday::Thu => 53, @@ -671,3 +677,18 @@ fn max_week_in_year(year: u32) -> u32 { fn is_leap_year(year: u32) -> bool { year % 400 == 0 || (year % 4 == 0 && year % 100 != 0) } + +/// https://html.spec.whatwg.org/multipage/#rules-for-parsing-floating-point-number-values +fn parse_floating_point_number(input: &str) -> Result { + match input.trim().parse::() { + Ok(val) if !( + // A valid number is the same as what rust considers to be valid, + // except for +1., NaN, and Infinity. + val.is_infinite() || val.is_nan() || input.ends_with(".") || input.starts_with("+") + ) => { + // TODO(#19773): need consider `min`, `max`, `step`, when they are implemented + Ok(val.round()) + }, + _ => Err(()) + } +} diff --git a/components/script/dom/htmlinputelement.rs b/components/script/dom/htmlinputelement.rs index 38f0287d63a6..ed153529889f 100755 --- a/components/script/dom/htmlinputelement.rs +++ b/components/script/dom/htmlinputelement.rs @@ -1047,11 +1047,17 @@ impl HTMLInputElement { } InputType::Number => { let mut textinput = self.textinput.borrow_mut(); - if !textinput.single_line_content().is_valid_number_string() { + if !textinput.single_line_content().is_valid_floating_point_number_string() { textinput.single_line_content_mut().clear(); } } - // TODO: Implement more value sanitization algorithms for different types of inputs + // https://html.spec.whatwg.org/multipage/#range-state-(type=range):value-sanitization-algorithm + InputType::Range => { + self.textinput + .borrow_mut() + .single_line_content_mut() + .set_best_representation_of_the_floating_point_number(); + } _ => () } } diff --git a/tests/wpt/metadata/MANIFEST.json b/tests/wpt/metadata/MANIFEST.json index baaa27bed20a..9d6b38dac249 100644 --- a/tests/wpt/metadata/MANIFEST.json +++ b/tests/wpt/metadata/MANIFEST.json @@ -550473,7 +550473,7 @@ "testharness" ], "html/semantics/forms/the-input-element/range.html": [ - "dd51c517a149c51e939a30dcad5e93f196e35cff", + "e992526fb5f117456a870e52c84eab5a7f4b14ab", "testharness" ], "html/semantics/forms/the-input-element/required_attribute.html": [ diff --git a/tests/wpt/metadata/html/semantics/forms/the-input-element/range-2.html.ini b/tests/wpt/metadata/html/semantics/forms/the-input-element/range-2.html.ini index 0ec31a9e420d..13c7333bf957 100644 --- a/tests/wpt/metadata/html/semantics/forms/the-input-element/range-2.html.ini +++ b/tests/wpt/metadata/html/semantics/forms/the-input-element/range-2.html.ini @@ -9,6 +9,6 @@ [range input value equals 100] expected: FAIL - [range input value equals 2] + [range input value set to an integer] expected: FAIL diff --git a/tests/wpt/metadata/html/semantics/forms/the-input-element/range.html.ini b/tests/wpt/metadata/html/semantics/forms/the-input-element/range.html.ini index 44f2b78ccc53..4cecdb935bbd 100644 --- a/tests/wpt/metadata/html/semantics/forms/the-input-element/range.html.ini +++ b/tests/wpt/metadata/html/semantics/forms/the-input-element/range.html.ini @@ -21,9 +21,6 @@ [default value when both min and max attributes are given, while min > max] expected: FAIL - [The default step scale factor is 1, unless min attribute has non-integer value] - expected: FAIL - [Step scale factor behavior when min attribute has integer value but max attribute is non-integer ] expected: FAIL diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/range.html b/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/range.html index 6ae5b8aeb3ca..209ce25306e0 100644 --- a/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/range.html +++ b/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/range.html @@ -34,6 +34,9 @@

Input Range

+ + +
@@ -280,6 +283,35 @@

Input Range

} ); + test( + function() { + var e = document.getElementById('should_skip_whitespace'); + assert_equals(e.value, "123") + }, "Skip ASCII whitespace within input", { + "help" : "https://html.spec.whatwg.org/multipage/#best-representation-of-the-number-as-a-floating-point-number" + } + ); + + test( + function() { + var e = document.getElementById('exponent_value1'); + e.value = 1e2; + assert_equals(e.value, "100") + }, "Multiply value by ten raised to the exponentth power with `e`", { + "help" : "https://html.spec.whatwg.org/multipage/#best-representation-of-the-number-as-a-floating-point-number" + } + ); + + test( + function() { + var e = document.getElementById('exponent_value2'); + e.value = 1E2; + assert_equals(e.value, "100") + }, "Multiply value by ten raised to the exponentth power with `E`", { + "help" : "https://html.spec.whatwg.org/multipage/#best-representation-of-the-number-as-a-floating-point-number" + } + ); +