LibJS: Handle out-of-range prefixed numbers in Token::double_value

This regressed in cd15b1a2c9.

If a prefixed number is out-of-range of a u64, stroul would previously
fall back to ULONG_MAX. This patch restores that behavior.
This commit is contained in:
Timothy Flynn 2025-08-10 06:41:15 -04:00 committed by Andreas Kling
parent 652a457f52
commit e2b245add1
2 changed files with 20 additions and 4 deletions

View File

@ -50,3 +50,18 @@ test("invalid numeric literals", () => {
expect("1in[]").not.toEval();
expect("2instanceof foo").not.toEval();
});
test("out-of-range literals", () => {
expect(0x10000000000000000).toBe(18446744073709552000);
expect(-0x10000000000000000).toBe(-18446744073709552000);
expect(0o2000000000000000000000).toBe(18446744073709552000);
expect(-0o2000000000000000000000).toBe(-18446744073709552000);
expect(0b10000000000000000000000000000000000000000000000000000000000000000).toBe(
18446744073709552000
);
expect(-0b10000000000000000000000000000000000000000000000000000000000000000).toBe(
-18446744073709552000
);
});

View File

@ -63,23 +63,24 @@ double Token::double_value() const
}
if (value.length() >= 2 && value.starts_with('0')) {
static constexpr auto fallback = NumericLimits<u64>::max();
auto next = value[1];
// hexadecimal
if (next == 'x' || next == 'X')
return static_cast<double>(value.substring_view(2).to_number<u64>(TrimWhitespace::No, 16).value());
return static_cast<double>(value.substring_view(2).to_number<u64>(TrimWhitespace::No, 16).value_or(fallback));
// octal
if (next == 'o' || next == 'O')
return static_cast<double>(value.substring_view(2).to_number<u64>(TrimWhitespace::No, 8).value());
return static_cast<double>(value.substring_view(2).to_number<u64>(TrimWhitespace::No, 8).value_or(fallback));
// binary
if (next == 'b' || next == 'B')
return static_cast<double>(value.substring_view(2).to_number<u64>(TrimWhitespace::No, 2).value());
return static_cast<double>(value.substring_view(2).to_number<u64>(TrimWhitespace::No, 2).value_or(fallback));
// also octal, but syntax error in strict mode
if (is_ascii_digit(next) && (!value.contains('8') && !value.contains('9')))
return static_cast<double>(value.substring_view(1).to_number<u64>(TrimWhitespace::No, 8).value());
return static_cast<double>(value.substring_view(1).to_number<u64>(TrimWhitespace::No, 8).value_or(fallback));
}
// This should always be a valid double