mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-27 06:43:32 +00:00
Bug 1870570 - Only allow exact matches for time zone and AM/PM keywords r=arai
Differential Revision: https://phabricator.services.mozilla.com/D196941
This commit is contained in:
parent
5d7f90295f
commit
015bc0177d
@ -1093,6 +1093,23 @@ bool IsPrefixOfKeyword(const CharT* s, size_t len, const char* keyword) {
|
||||
return len == 0;
|
||||
}
|
||||
|
||||
template <typename CharT>
|
||||
bool MatchesKeyword(const CharT* s, size_t len, const char* keyword) {
|
||||
while (len > 0) {
|
||||
MOZ_ASSERT(IsAsciiAlpha(*s));
|
||||
MOZ_ASSERT(IsAsciiLowercaseAlpha(*keyword));
|
||||
|
||||
if (unicode::ToLowerCase(static_cast<Latin1Char>(*s)) != *keyword) {
|
||||
return false;
|
||||
}
|
||||
|
||||
++s, ++keyword;
|
||||
--len;
|
||||
}
|
||||
|
||||
return *keyword == '\0';
|
||||
}
|
||||
|
||||
static constexpr const char* const month_prefixes[] = {
|
||||
"jan", "feb", "mar", "apr", "may", "jun",
|
||||
"jul", "aug", "sep", "oct", "nov", "dec",
|
||||
@ -1318,19 +1335,15 @@ struct CharsAndAction {
|
||||
int action;
|
||||
};
|
||||
|
||||
static constexpr const char* const days_of_week[] = {
|
||||
"monday", "tuesday", "wednesday", "thursday",
|
||||
"friday", "saturday", "sunday"};
|
||||
|
||||
static constexpr CharsAndAction keywords[] = {
|
||||
// clang-format off
|
||||
// AM/PM
|
||||
{ "am", -1 },
|
||||
{ "pm", -2 },
|
||||
// Days of week.
|
||||
{ "monday", 0 },
|
||||
{ "tuesday", 0 },
|
||||
{ "wednesday", 0 },
|
||||
{ "thursday", 0 },
|
||||
{ "friday", 0 },
|
||||
{ "saturday", 0 },
|
||||
{ "sunday", 0 },
|
||||
// Time zone abbreviations.
|
||||
{ "gmt", 10000 + 0 },
|
||||
{ "z", 10000 + 0 },
|
||||
@ -1650,6 +1663,21 @@ static bool ParseDate(DateTimeInfo::ForceUTC forceUTC, const CharT* s,
|
||||
return false;
|
||||
}
|
||||
|
||||
// Completely ignore days of the week, and don't derive any semantics
|
||||
// from them.
|
||||
bool isLateWeekday = false;
|
||||
for (const char* weekday : days_of_week) {
|
||||
if (IsPrefixOfKeyword(s + start, index - start, weekday)) {
|
||||
isLateWeekday = true;
|
||||
seenLateWeekday = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (isLateWeekday) {
|
||||
prevc = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
size_t k = std::size(keywords);
|
||||
while (k-- > 0) {
|
||||
// Record a month if it is a month name. Note that some numbers are
|
||||
@ -1692,21 +1720,13 @@ static bool ParseDate(DateTimeInfo::ForceUTC forceUTC, const CharT* s,
|
||||
|
||||
const CharsAndAction& keyword = keywords[k];
|
||||
|
||||
// If the field isn't a prefix of the keyword (an exact match is *not*
|
||||
// required), try the next one.
|
||||
if (!IsPrefixOfKeyword(s + start, index - start, keyword.chars)) {
|
||||
// If the field doesn't match the keyword, try the next one.
|
||||
if (!MatchesKeyword(s + start, index - start, keyword.chars)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int action = keyword.action;
|
||||
|
||||
// Completely ignore days of the week, and don't derive any semantics
|
||||
// from them.
|
||||
if (action == 0) {
|
||||
seenLateWeekday = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (action == 10000) {
|
||||
seenGmtAbbr = true;
|
||||
}
|
||||
|
49
js/src/tests/non262/Date/parse-keywords.js
Normal file
49
js/src/tests/non262/Date/parse-keywords.js
Normal file
@ -0,0 +1,49 @@
|
||||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
const accepted = {
|
||||
"Sep 26 1995 UT": "1995-09-26T00:00:00Z",
|
||||
"Sep 26 1995 UTC": "1995-09-26T00:00:00Z",
|
||||
"Sep 26 1995 GMT": "1995-09-26T00:00:00Z",
|
||||
"Sep 26 1995 EST": "1995-09-26T00:00:00-0500",
|
||||
"Sep 26 1995 est": "1995-09-26T00:00:00-0500",
|
||||
"Sep 26 1995 10:00 am": "1995-09-26T10:00:00",
|
||||
"Sep 26 1995 10:00 AM": "1995-09-26T10:00:00",
|
||||
"Sep 26 1995 10:00 pm": "1995-09-26T22:00:00",
|
||||
"Sep 26 Thurs 1995 Mon 10:thursday:00": "1995-09-26T10:00:00",
|
||||
};
|
||||
const rejected = [
|
||||
"Sep 26 1995 G",
|
||||
"Sep 26 1995 GM",
|
||||
"Sep 26 1995 E",
|
||||
"Sep 26 1995 ES",
|
||||
"Sep 26 1995 10:00 a",
|
||||
"Sep 26 1995 10:00 p",
|
||||
];
|
||||
|
||||
for (const [test, expected] of Object.entries(accepted)) {
|
||||
const testDate = new Date(test);
|
||||
const expectedDate = new Date(expected);
|
||||
|
||||
assertEq(
|
||||
false, isNaN(testDate),
|
||||
`${test} should be accepted.`
|
||||
);
|
||||
|
||||
assertEq(
|
||||
testDate.getTime(), expectedDate.getTime(),
|
||||
`"${test}" should be ${expectedDate} (got ${testDate}).`
|
||||
);
|
||||
}
|
||||
|
||||
for (const reject of rejected) {
|
||||
assertEq(
|
||||
true, isNaN(new Date(reject)),
|
||||
`"${reject}" should be rejected.`
|
||||
);
|
||||
}
|
||||
|
||||
if (typeof reportCompare === "function")
|
||||
reportCompare(true, true);
|
Loading…
Reference in New Issue
Block a user