From 66afb7234cf53957094509014cc5e97fa152b0f4 Mon Sep 17 00:00:00 2001 From: bptato Date: Tue, 24 Mar 2026 19:44:11 +0100 Subject: [PATCH] Fix member access on non-decimal numeric literals In other engines, 0x0.toString() returns '0', but QJS would try to parse it as a float and then throw. Also removes remnants of hex float parsing which is no longer supported anyway. (Port of https://github.com/quickjs-ng/quickjs/pull/377) --- quickjs.c | 22 +++++----------------- tests/test_language.js | 11 +++++++++++ 2 files changed, 16 insertions(+), 17 deletions(-) diff --git a/quickjs.c b/quickjs.c index 0f681d9..9a1eb87 100644 --- a/quickjs.c +++ b/quickjs.c @@ -12436,7 +12436,7 @@ static JSValue js_atof(JSContext *ctx, const char *str, const char **pp, to_digit((uint8_t)p[1]) < radix)) { p++; } - if (!(flags & ATOD_INT_ONLY)) { + if (!(flags & ATOD_INT_ONLY) && radix == 10) { if (*p == '.' && (p > p_start || to_digit((uint8_t)p[1]) < radix)) { is_float = TRUE; p++; @@ -12446,9 +12446,7 @@ static JSValue js_atof(JSContext *ctx, const char *str, const char **pp, (*p == sep && to_digit((uint8_t)p[1]) < radix)) p++; } - if (p > p_start && - (((*p == 'e' || *p == 'E') && radix == 10) || - ((*p == 'p' || *p == 'P') && (radix == 2 || radix == 8 || radix == 16)))) { + if (p > p_start && (*p == 'e' || *p == 'E')) { const char *p1 = p + 1; is_float = TRUE; if (*p1 == '+') { @@ -12485,19 +12483,9 @@ static JSValue js_atof(JSContext *ctx, const char *str, const char **pp, } buf[j] = '\0'; - if (flags & ATOD_ACCEPT_SUFFIX) { - if (*p == 'n') { - p++; - atod_type = ATOD_TYPE_BIG_INT; - } else { - if (is_float && radix != 10) - goto fail; - } - } else { - if (atod_type == ATOD_TYPE_FLOAT64) { - if (is_float && radix != 10) - goto fail; - } + if ((flags & ATOD_ACCEPT_SUFFIX) && *p == 'n') { + p++; + atod_type = ATOD_TYPE_BIG_INT; } switch(atod_type) { diff --git a/tests/test_language.js b/tests/test_language.js index 5c51f0d..f658044 100644 --- a/tests/test_language.js +++ b/tests/test_language.js @@ -664,6 +664,16 @@ function test_global_var_opt() assert(gvar1, 5); } +function test_number_literals() +{ + assert(0.1.a, undefined); + assert(0x1.a, undefined); + assert(0b1.a, undefined); + assert(01.a, undefined); + assert(0o1.a, undefined); + assert_throws(SyntaxError, () => eval('0.a')); +} + test_op1(); test_cvt(); test_eq(); @@ -690,3 +700,4 @@ test_optional_chaining(); test_parse_arrow_function(); test_unicode_ident(); test_global_var_opt(); +test_number_literals();