Date parsing rejects valid dates with zero-padded numeric fields
Categories
(Core :: JavaScript Engine, defect, P3)
Tracking
()
People
(Reporter: zzjas98, Unassigned)
References
(Blocks 1 open bug)
Details
(Keywords: parity-chrome)
Steps to reproduce:
// js --fuzzing-safe poc.js
function test(input, expected) {
var d = new Date(input);
var ok = !isNaN(d.getTime()) === !isNaN(expected.getTime());
var tag = ok ? "OK " : "BUG";
print(tag + " : new Date('" + input + "') -> " + d);
}
// --- Variant 1: zero-padded day blocked by yearDigits < 4 guard (line 1399) ---
test("2032-Apr-24", new Date("2032-Apr-24")); // OK baseline
test("2032-Apr-0024", new Date("2032-Apr-24")); // BUG: Invalid Date
// --- Variant 2a: seenFullYear blocks seenMonthName swap (line 1991) ---
test("32 Apr 23", new Date("32 Apr 23")); // OK baseline
test("32 Apr 0023", new Date("32 Apr 23")); // BUG: NaN
// --- Variant 2b: seenFullYear blocks numeric month/day reorder (line 2005) ---
test("2032 4 23", new Date("2032 4 23")); // OK baseline
test("2032 4 0023", new Date("2032 4 23")); // BUG: NaN
Actual results:
OK : new Date('2032-Apr-24') -> Sat Apr 24 2032 00:00:00 GMT-0500 (Central Daylight Time)
BUG : new Date('2032-Apr-0024') -> Invalid Date
OK : new Date('32 Apr 23') -> Fri Apr 23 2032 00:00:00 GMT-0500 (Central Daylight Time)
BUG : new Date('32 Apr 0023') -> Invalid Date
OK : new Date('2032 4 23') -> Fri Apr 23 2032 00:00:00 GMT-0500 (Central Daylight Time)
BUG : new Date('2032 4 0023') -> Invalid Date
Expected results:
OK : new Date('2032-Apr-24') -> Sat Apr 24 2032 00:00:00 GMT-0500 (Central Daylight Time)
OK : new Date('2032-Apr-0024') -> Sat Apr 24 2032 00:00:00 GMT-0500 (Central Daylight Time)
OK : new Date('32 Apr 23') -> Fri Apr 23 2032 00:00:00 GMT-0500 (Central Daylight Time)
OK : new Date('32 Apr 0023') -> Fri Apr 23 2032 00:00:00 GMT-0500 (Central Daylight Time)
OK : new Date('2032 4 23') -> Fri Apr 23 2032 00:00:00 GMT-0500 (Central Daylight Time)
OK : new Date('2032 4 0023') -> Fri Apr 23 2032 00:00:00 GMT-0500 (Central Daylight Time)
Analysis
Two related bugs in js/src/builtin/Date.cpp where digit count is used as a proxy for semantic value, causing zero-padded fields to be misclassified.
Variant 1 (yearDigits): TryParseDashedDatePrefix at line 1399 guards the year/day swap with yearDigits < 4. A day value like "0024" has yearDigits=4 (digit count, not numeric value), so the swap is skipped and the date is rejected as invalid.
Variant 2 (seenFullYear): seenFullYear = partLength >= 4 at line 1820 marks a zero-padded year like "0023" (value 23) as a full year because it has 4 digits. This blocks the field-swap heuristics guarded by !seenFullYear at lines 1991 and 2005, returning NaN for otherwise valid date strings.
Tested on commit 16a7dee3ca6fb0967cd84314393ad1d2e213e4a6.
Please let me know if I can provide any more information, thanks!
Comment 1•4 months ago
|
||
Thank you for your report!
All those syntax are not a part of the spec, and thus it's up to each implementation to accept or not.
So, technically, those dates are not necessarily "valid", but implementations can accept it.
https://tc39.es/ecma262/#sec-date.parse
https://tc39.es/ecma262/#sec-date-time-string-format
The current situation around the support seems to be the following:
- V8, GraalJS, and QuickJS accepts them
- engine262 also accepts them, but using V8's date parser
- JavaScriptCore, XS, Boa, and SpiderMonkey rejects them
Given that multiple engines support them, it would make sense to support them in SpiderMonkey as well.
Vinny, are you available for looking into this?
Updated•4 months ago
|
Comment 2•4 months ago
|
||
If such invalid inputs are already rejected as such by a significant fraction of all implementations (and two-thirds of major browser implementations), it would be nice to not increase leniency.
Comment 3•3 months ago
|
||
Redirect a needinfo that is pending on an inactive user to the triage owner.
:gtonietto, since the bug has recent activity, could you have a look please?
For more information, please visit BugBot documentation.
Comment 4•3 months ago
|
||
Okay, if they're busy, then let's put this into backlog.
Description
•