Skip to content

Commit e6cebad

Browse files
authored
Fix date parsing in case there is more than nine initial digits
Backport from upstream: bellard/quickjs@030333c Most engines like v8, and current versions of spidermonkey versions (v128 at least) return NaN while QuickJS parses up to 9 digits at a time, then tries to parse the rest. Trying to parse extra digits can sometimes produce random garbage. To fix it, when parsing the initial integer parse as many digits as we can (max = 0) instead of just 9. Add a few tests, including uncommenting some previous ones, and ensure they pass on v8 version 11 (upstream didn't include the extra tests).
1 parent 97e6ef9 commit e6cebad

File tree

2 files changed

+23
-5
lines changed

2 files changed

+23
-5
lines changed

quickjs.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50723,6 +50723,9 @@ static bool string_get_digits(const uint8_t *sp, int *pp, int *pval,
5072350723

5072450724
p_start = p;
5072550725
while ((c = sp[p]) >= '0' && c <= '9') {
50726+
/* arbitrary limit to 9 digits */
50727+
if (v >= 100000000)
50728+
return false;
5072650729
v = v * 10 + c - '0';
5072750730
p++;
5072850731
if (p - p_start == max_digits)
@@ -50766,7 +50769,7 @@ static bool string_get_tzoffset(const uint8_t *sp, int *pp, int *tzp, bool stric
5076650769
sgn = sp[p++];
5076750770
if (sgn == '+' || sgn == '-') {
5076850771
int n = p;
50769-
if (!string_get_digits(sp, &p, &hh, 1, 9))
50772+
if (!string_get_digits(sp, &p, &hh, 1, 0))
5077050773
return false;
5077150774
n = p - n;
5077250775
if (strict && n != 2 && n != 4)
@@ -50960,7 +50963,7 @@ static bool js_date_parse_otherstring(const uint8_t *sp,
5096050963
*is_local = false;
5096150964
} else {
5096250965
p++;
50963-
if (string_get_digits(sp, &p, &val, 1, 9)) {
50966+
if (string_get_digits(sp, &p, &val, 1, 0)) {
5096450967
if (c == '-') {
5096550968
if (val == 0)
5096650969
return false;
@@ -50971,7 +50974,7 @@ static bool js_date_parse_otherstring(const uint8_t *sp,
5097150974
}
5097250975
}
5097350976
} else
50974-
if (string_get_digits(sp, &p, &val, 1, 9)) {
50977+
if (string_get_digits(sp, &p, &val, 1, 0)) {
5097550978
if (string_skip_char(sp, &p, ':')) {
5097650979
/* time part */
5097750980
fields[3] = val;

tests/test_builtin.js

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -608,11 +608,26 @@ function test_date()
608608
// Hence the fractional part after . should have 3 digits and how
609609
// a different number of digits is handled is implementation defined.
610610
assert(Date.parse(""), NaN);
611+
assert(Date.parse("13"), NaN);
612+
assert(Date.parse("31"), NaN);
613+
assert(Date.parse("1000"), -30610224000000);
614+
assert(Date.parse("1969"), -31536000000);
615+
assert(Date.parse("1970"), 0);
611616
assert(Date.parse("2000"), 946684800000);
617+
assert(Date.parse("9999"), 253370764800000);
618+
assert(Date.parse("275761"), NaN);
619+
assert(Date.parse("999999"), NaN);
620+
assert(Date.parse("1000000000"), NaN);
621+
assert(Date.parse("-271821"), NaN);
622+
assert(Date.parse("-271820"), -8639977881600000);
623+
assert(Date.parse("-100000"), -3217862419200000);
624+
assert(Date.parse("+100000"), 3093527980800000);
625+
assert(Date.parse("+275760"), 8639977881600000);
626+
assert(Date.parse("+275761"), NaN);
612627
assert(Date.parse("2000-01"), 946684800000);
613628
assert(Date.parse("2000-01-01"), 946684800000);
614-
//assert(Date.parse("2000-01-01T"), NaN);
615-
//assert(Date.parse("2000-01-01T00Z"), NaN);
629+
assert(Date.parse("2000-01-01T"), NaN);
630+
assert(Date.parse("2000-01-01T00Z"), NaN);
616631
assert(Date.parse("2000-01-01T00:00Z"), 946684800000);
617632
assert(Date.parse("2000-01-01T00:00:00Z"), 946684800000);
618633
assert(Date.parse("2000-01-01T00:00:00.1Z"), 946684800100);

0 commit comments

Comments
 (0)