From 4a7f1fa01bf0cb89dbaaae5e54238350a410aa44 Mon Sep 17 00:00:00 2001 From: Weixie Cui Date: Fri, 27 Mar 2026 14:11:07 +0800 Subject: [PATCH] Parse full-range hex literals with strtoull Hex literals like 0xFFFFFFFFFFFFFFFF exceed signed long long; strtoll overflows and errno becomes ERANGE, incorrectly rejecting the literal. Use strtoull and cast to double. Add a regression test for UINT64_MAX. --- src/vm/wren_compiler.c | 4 ++-- test/core/number/hex_literal_uint64_max.wren | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) create mode 100644 test/core/number/hex_literal_uint64_max.wren diff --git a/src/vm/wren_compiler.c b/src/vm/wren_compiler.c index 47705f5e4..b67e9928c 100644 --- a/src/vm/wren_compiler.c +++ b/src/vm/wren_compiler.c @@ -750,7 +750,7 @@ static void makeNumber(Parser* parser, bool isHex) if (isHex) { - parser->next.value = NUM_VAL((double)strtoll(parser->tokenStart, NULL, 16)); + parser->next.value = NUM_VAL((double)strtoull(parser->tokenStart, NULL, 16)); } else { @@ -763,7 +763,7 @@ static void makeNumber(Parser* parser, bool isHex) parser->next.value = NUM_VAL(0); } - // We don't check that the entire token is consumed after calling strtoll() + // We don't check that the entire token is consumed after calling strtoull() // or strtod() because we've already scanned it ourselves and know it's valid. makeToken(parser, TOKEN_NUMBER); diff --git a/test/core/number/hex_literal_uint64_max.wren b/test/core/number/hex_literal_uint64_max.wren new file mode 100644 index 000000000..9901a602a --- /dev/null +++ b/test/core/number/hex_literal_uint64_max.wren @@ -0,0 +1,2 @@ +// 0xFFFFFFFFFFFFFFFF overflows signed strtoll; must parse as unsigned (strtoull). +System.print(0xFFFFFFFFFFFFFFFF) // expect: 1.844674407371e+19