浏览代码

LibWeb: Treat dates and times with repeated separators as invalid

These would previously be treated as valid by the value sanitization
algorithm.
Tim Ledbetter 10 月之前
父节点
当前提交
f9282f65d3

+ 5 - 0
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 "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 "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 "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 "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-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-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 "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 "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 "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 "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 "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 "23:59:59"
+Changing type from "text" to "time" changes value from "23::59::59" to ""

+ 5 - 0
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: "number", initialValue: "not-a-number" },
             { initialType: "text", newType: "date", initialValue: "not-a-date" },
             { 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: "date", initialValue: "2024--09--10" },
             { initialType: "text", newType: "datetime-local", initialValue: "not-a-local-datetime" },
             { 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-10 23:59" },
             { initialType: "text", newType: "datetime-local", initialValue: "2024-09-10T23: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: "not-a-month" },
             { initialType: "text", newType: "month", initialValue: "2024-09" },
             { 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: "not-a-week" },
             { initialType: "text", newType: "week", initialValue: "2024-W26" },
             { 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: "not-a-time" },
             { initialType: "text", newType: "time", initialValue: "23:59:59" },
             { initialType: "text", newType: "time", initialValue: "23:59:59" },
+            { initialType: "text", newType: "time", initialValue: "23::59::59" },
         ];
         ];
         for (const { initialType, newType, initialValue } of testData) {
         for (const { initialType, newType, initialValue } of testData) {
             const inputElement = document.createElement("input");
             const inputElement = document.createElement("input");

+ 9 - 9
Userland/Libraries/LibWeb/HTML/Dates.cpp

@@ -40,7 +40,7 @@ bool is_valid_week_string(StringView value)
     // 2. A U+002D HYPHEN-MINUS character (-)
     // 2. A U+002D HYPHEN-MINUS character (-)
     // 3. A U+0057 LATIN CAPITAL LETTER W character (W)
     // 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
     // 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)
     if (parts.size() != 2)
         return false;
         return false;
     if (parts[0].length() < 4)
     if (parts[0].length() < 4)
@@ -77,7 +77,7 @@ bool is_valid_month_string(StringView value)
     // 2. A U+002D HYPHEN-MINUS character (-)
     // 2. A U+002D HYPHEN-MINUS character (-)
     // 3. Two ASCII digits, representing the month month, in the range 1 ≤ month ≤ 12
     // 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)
     if (parts.size() != 2)
         return false;
         return false;
 
 
@@ -107,7 +107,7 @@ bool is_valid_date_string(StringView value)
     // 1. A valid month string, representing year and month
     // 1. A valid month string, representing year and month
     // 2. A U+002D HYPHEN-MINUS character (-)
     // 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
     // 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)
     if (parts.size() != 3)
         return false;
         return false;
 
 
@@ -132,7 +132,7 @@ bool is_valid_date_string(StringView value)
 WebIDL::ExceptionOr<JS::NonnullGCPtr<JS::Date>> parse_date_string(JS::Realm& realm, StringView value)
 WebIDL::ExceptionOr<JS::NonnullGCPtr<JS::Date>> parse_date_string(JS::Realm& realm, StringView value)
 {
 {
     // FIXME: Implement spec compliant date string parsing
     // FIXME: Implement spec compliant date string parsing
-    auto parts = value.split_view('-');
+    auto parts = value.split_view('-', SplitBehavior::KeepEmpty);
     if (parts.size() >= 3) {
     if (parts.size() >= 3) {
         if (auto year = parts.at(0).to_number<u32>(); year.has_value()) {
         if (auto year = parts.at(0).to_number<u32>(); year.has_value()) {
             if (auto month = parts.at(1).to_number<u32>(); month.has_value()) {
             if (auto month = parts.at(1).to_number<u32>(); month.has_value()) {
@@ -147,10 +147,10 @@ WebIDL::ExceptionOr<JS::NonnullGCPtr<JS::Date>> parse_date_string(JS::Realm& rea
 // https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#valid-local-date-and-time-string
 // 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)
 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)
     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]);
         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)
     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]);
         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:
     // 3. If second is not an integer, or optionally if second is an integer:
     // 1. A U+002E FULL STOP character (.)
     // 1. A U+002E FULL STOP character (.)
     // 2. One, two, or three ASCII digits, representing the fractional part of second
     // 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)
     if (parts.size() != 2 && parts.size() != 3)
         return false;
         return false;
     if (parts[0].length() != 2)
     if (parts[0].length() != 2)
@@ -212,7 +212,7 @@ bool is_valid_time_string(StringView value)
         return false;
         return false;
     if (parts[2].length() == 2)
     if (parts[2].length() == 2)
         return true;
         return true;
-    auto second_parts = parts[2].split_view('.');
+    auto second_parts = parts[2].split_view('.', SplitBehavior::KeepEmpty);
     if (second_parts.size() != 2)
     if (second_parts.size() != 2)
         return false;
         return false;
     if (second_parts[1].length() < 1 || second_parts[1].length() > 3)
     if (second_parts[1].length() < 1 || second_parts[1].length() > 3)
@@ -228,7 +228,7 @@ bool is_valid_time_string(StringView value)
 WebIDL::ExceptionOr<JS::NonnullGCPtr<JS::Date>> parse_time_string(JS::Realm& realm, StringView value)
 WebIDL::ExceptionOr<JS::NonnullGCPtr<JS::Date>> parse_time_string(JS::Realm& realm, StringView value)
 {
 {
     // FIXME: Implement spec compliant time string parsing
     // FIXME: Implement spec compliant time string parsing
-    auto parts = value.split_view(':');
+    auto parts = value.split_view(':', SplitBehavior::KeepEmpty);
     if (parts.size() >= 2) {
     if (parts.size() >= 2) {
         if (auto hours = parts.at(0).to_number<u32>(); hours.has_value()) {
         if (auto hours = parts.at(0).to_number<u32>(); hours.has_value()) {
             if (auto minutes = parts.at(1).to_number<u32>(); minutes.has_value()) {
             if (auto minutes = parts.at(1).to_number<u32>(); minutes.has_value()) {