From f9282f65d3a4daf7df2c6033b03c70a56130aa72 Mon Sep 17 00:00:00 2001 From: Tim Ledbetter Date: Tue, 10 Sep 2024 16:53:05 +0100 Subject: [PATCH] LibWeb: Treat dates and times with repeated separators as invalid These would previously be treated as valid by the value sanitization algorithm. --- .../HTMLInputElement-type-state-change.txt | 5 +++++ .../HTMLInputElement-type-state-change.html | 5 +++++ Userland/Libraries/LibWeb/HTML/Dates.cpp | 18 +++++++++--------- 3 files changed, 19 insertions(+), 9 deletions(-) diff --git a/Tests/LibWeb/Text/expected/HTML/HTMLInputElement-type-state-change.txt b/Tests/LibWeb/Text/expected/HTML/HTMLInputElement-type-state-change.txt index 47dc78ca661..d3a514f260d 100644 --- a/Tests/LibWeb/Text/expected/HTML/HTMLInputElement-type-state-change.txt +++ b/Tests/LibWeb/Text/expected/HTML/HTMLInputElement-type-state-change.txt @@ -10,12 +10,17 @@ Changing type from "text" to "number" changes value from "123.45" to "123.45" Changing type from "text" to "number" changes value from "not-a-number" to "" Changing type from "text" to "date" changes value from "not-a-date" to "" Changing type from "text" to "date" changes value from "2024-09-10" to "2024-09-10" +Changing type from "text" to "date" changes value from "2024--09--10" to "" Changing type from "text" to "datetime-local" changes value from "not-a-local-datetime" to "" Changing type from "text" to "datetime-local" changes value from "2024-09-10 23:59" to "2024-09-10T23:59" Changing type from "text" to "datetime-local" changes value from "2024-09-10T23:59" to "2024-09-10T23:59" +Changing type from "text" to "datetime-local" changes value from "2024--09--10TT23::59" to "" Changing type from "text" to "month" changes value from "not-a-month" to "" Changing type from "text" to "month" changes value from "2024-09" to "2024-09" +Changing type from "text" to "month" changes value from "2024--09" to "" Changing type from "text" to "week" changes value from "not-a-week" to "" Changing type from "text" to "week" changes value from "2024-W26" to "2024-W26" +Changing type from "text" to "week" changes value from "2024--W26" to "" Changing type from "text" to "time" changes value from "not-a-time" to "" Changing type from "text" to "time" changes value from "23:59:59" to "23:59:59" +Changing type from "text" to "time" changes value from "23::59::59" to "" diff --git a/Tests/LibWeb/Text/input/HTML/HTMLInputElement-type-state-change.html b/Tests/LibWeb/Text/input/HTML/HTMLInputElement-type-state-change.html index cffb198ff7b..e4bf7441e97 100644 --- a/Tests/LibWeb/Text/input/HTML/HTMLInputElement-type-state-change.html +++ b/Tests/LibWeb/Text/input/HTML/HTMLInputElement-type-state-change.html @@ -15,15 +15,20 @@ { initialType: "text", newType: "number", initialValue: "not-a-number" }, { initialType: "text", newType: "date", initialValue: "not-a-date" }, { initialType: "text", newType: "date", initialValue: "2024-09-10" }, + { initialType: "text", newType: "date", initialValue: "2024--09--10" }, { initialType: "text", newType: "datetime-local", initialValue: "not-a-local-datetime" }, { initialType: "text", newType: "datetime-local", initialValue: "2024-09-10 23:59" }, { initialType: "text", newType: "datetime-local", initialValue: "2024-09-10T23:59" }, + { initialType: "text", newType: "datetime-local", initialValue: "2024--09--10TT23::59" }, { initialType: "text", newType: "month", initialValue: "not-a-month" }, { initialType: "text", newType: "month", initialValue: "2024-09" }, + { initialType: "text", newType: "month", initialValue: "2024--09" }, { initialType: "text", newType: "week", initialValue: "not-a-week" }, { initialType: "text", newType: "week", initialValue: "2024-W26" }, + { initialType: "text", newType: "week", initialValue: "2024--W26" }, { initialType: "text", newType: "time", initialValue: "not-a-time" }, { initialType: "text", newType: "time", initialValue: "23:59:59" }, + { initialType: "text", newType: "time", initialValue: "23::59::59" }, ]; for (const { initialType, newType, initialValue } of testData) { const inputElement = document.createElement("input"); diff --git a/Userland/Libraries/LibWeb/HTML/Dates.cpp b/Userland/Libraries/LibWeb/HTML/Dates.cpp index 1aa42c81425..48ec20b96ea 100644 --- a/Userland/Libraries/LibWeb/HTML/Dates.cpp +++ b/Userland/Libraries/LibWeb/HTML/Dates.cpp @@ -40,7 +40,7 @@ bool is_valid_week_string(StringView value) // 2. A U+002D HYPHEN-MINUS character (-) // 3. A U+0057 LATIN CAPITAL LETTER W character (W) // 4. Two ASCII digits, representing the week week, in the range 1 ≤ week ≤ maxweek, where maxweek is the week number of the last day of week-year year - auto parts = value.split_view('-'); + auto parts = value.split_view('-', SplitBehavior::KeepEmpty); if (parts.size() != 2) return false; if (parts[0].length() < 4) @@ -77,7 +77,7 @@ bool is_valid_month_string(StringView value) // 2. A U+002D HYPHEN-MINUS character (-) // 3. Two ASCII digits, representing the month month, in the range 1 ≤ month ≤ 12 - auto parts = value.split_view('-'); + auto parts = value.split_view('-', SplitBehavior::KeepEmpty); if (parts.size() != 2) return false; @@ -107,7 +107,7 @@ bool is_valid_date_string(StringView value) // 1. A valid month string, representing year and month // 2. A U+002D HYPHEN-MINUS character (-) // 3. Two ASCII digits, representing day, in the range 1 ≤ day ≤ maxday where maxday is the number of days in the month month and year year - auto parts = value.split_view('-'); + auto parts = value.split_view('-', SplitBehavior::KeepEmpty); if (parts.size() != 3) return false; @@ -132,7 +132,7 @@ bool is_valid_date_string(StringView value) WebIDL::ExceptionOr> parse_date_string(JS::Realm& realm, StringView value) { // FIXME: Implement spec compliant date string parsing - auto parts = value.split_view('-'); + auto parts = value.split_view('-', SplitBehavior::KeepEmpty); if (parts.size() >= 3) { if (auto year = parts.at(0).to_number(); year.has_value()) { if (auto month = parts.at(1).to_number(); month.has_value()) { @@ -147,10 +147,10 @@ WebIDL::ExceptionOr> parse_date_string(JS::Realm& rea // https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#valid-local-date-and-time-string bool is_valid_local_date_and_time_string(StringView value) { - auto parts_split_by_T = value.split_view('T'); + auto parts_split_by_T = value.split_view('T', SplitBehavior::KeepEmpty); if (parts_split_by_T.size() == 2) return is_valid_date_string(parts_split_by_T[0]) && is_valid_time_string(parts_split_by_T[1]); - auto parts_split_by_space = value.split_view(' '); + auto parts_split_by_space = value.split_view(' ', SplitBehavior::KeepEmpty); if (parts_split_by_space.size() == 2) return is_valid_date_string(parts_split_by_space[0]) && is_valid_time_string(parts_split_by_space[1]); @@ -183,7 +183,7 @@ bool is_valid_time_string(StringView value) // 3. If second is not an integer, or optionally if second is an integer: // 1. A U+002E FULL STOP character (.) // 2. One, two, or three ASCII digits, representing the fractional part of second - auto parts = value.split_view(':'); + auto parts = value.split_view(':', SplitBehavior::KeepEmpty); if (parts.size() != 2 && parts.size() != 3) return false; if (parts[0].length() != 2) @@ -212,7 +212,7 @@ bool is_valid_time_string(StringView value) return false; if (parts[2].length() == 2) return true; - auto second_parts = parts[2].split_view('.'); + auto second_parts = parts[2].split_view('.', SplitBehavior::KeepEmpty); if (second_parts.size() != 2) return false; if (second_parts[1].length() < 1 || second_parts[1].length() > 3) @@ -228,7 +228,7 @@ bool is_valid_time_string(StringView value) WebIDL::ExceptionOr> parse_time_string(JS::Realm& realm, StringView value) { // FIXME: Implement spec compliant time string parsing - auto parts = value.split_view(':'); + auto parts = value.split_view(':', SplitBehavior::KeepEmpty); if (parts.size() >= 2) { if (auto hours = parts.at(0).to_number(); hours.has_value()) { if (auto minutes = parts.at(1).to_number(); minutes.has_value()) {