From 6434bf4b659a619b767e2a90047d9904f2bd565f Mon Sep 17 00:00:00 2001 From: Jeroen van Rijn Date: Sat, 7 Mar 2026 12:38:04 +0100 Subject: [PATCH] Limit maximum exponent in parsing of float/integer literals --- core/c/libc/math.odin | 2 +- src/big_int.cpp | 22 ++++++++++++++++++++-- src/parser.cpp | 7 ++++++- 3 files changed, 27 insertions(+), 4 deletions(-) diff --git a/core/c/libc/math.odin b/core/c/libc/math.odin index d0a015c70..434b67817 100644 --- a/core/c/libc/math.odin +++ b/core/c/libc/math.odin @@ -159,7 +159,7 @@ float_t :: float double_t :: double NAN := transmute(double)(_nan_bit_pattern) -INFINITY :: 1e5000 +INFINITY :: 0h7ff00000_00000000 // +Inf HUGE_VALF :: INFINITY HUGE_VAL :: double(INFINITY) diff --git a/src/big_int.cpp b/src/big_int.cpp index 0b0a9a400..7067a7c3d 100644 --- a/src/big_int.cpp +++ b/src/big_int.cpp @@ -197,8 +197,13 @@ gb_internal void big_int_from_string(BigInt *dst, String const &s, bool *success BigInt b = {}; big_int_from_u64(&b, base); + defer (big_int_dealloc(&b)); + mp_zero(dst); + BigInt digit = {}; + defer (big_int_dealloc(&digit)); + isize i = 0; for (; i < len; i++) { Rune r = cast(Rune)text[i]; @@ -224,9 +229,10 @@ gb_internal void big_int_from_string(BigInt *dst, String const &s, bool *success } break; } - BigInt val = big_int_make_u64(v); + + big_int_from_u64(&digit, v); big_int_mul_eq(dst, &b); - big_int_add_eq(dst, &val); + big_int_add_eq(dst, &digit); } if (i < len && (text[i] == 'e' || text[i] == 'E')) { i += 1; @@ -235,6 +241,7 @@ gb_internal void big_int_from_string(BigInt *dst, String const &s, bool *success if (text[i] == '+') { i += 1; } + u64 exp = 0; for (; i < len; i++) { char r = cast(char)text[i]; @@ -251,8 +258,19 @@ gb_internal void big_int_from_string(BigInt *dst, String const &s, bool *success exp *= 10; exp += v; } + + // NOTE(Jeroen): A valid integer can never have an exponent larger than 308 (per `max(f64)`). + // As an integer, not even larger than `max(u128)` which has a base 10 exponent of 38. + // But we also use this path to parse float literals like those in `core:math.pow10_f64`, + // so we have to stick with 1e308. + if (exp > 308) { + *success = false; + return; + } + BigInt tmp = {}; mp_init(&tmp); + defer (big_int_dealloc(&tmp)); big_int_exp_u64(&tmp, &b, exp, success); big_int_mul_eq(dst, &tmp); } diff --git a/src/parser.cpp b/src/parser.cpp index 84fbc5130..ca81159b4 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -804,7 +804,12 @@ gb_internal ExactValue exact_value_from_token(AstFile *f, Token const &token) { syntax_error(token, "Invalid integer literal"); break; case Token_Float: - syntax_error(token, "Invalid float literal"); + // NOTE(Jeroen): Could be an integer, see `exact_value_float_from_string` + if (!string_contains_char(s, '.') && !string_contains_char(s, '-')) { + syntax_error(token, "Invalid integer literal"); + } else { + syntax_error(token, "Invalid float literal"); + } break; default: syntax_error(token, "Invalid token literal");