Limit maximum exponent in parsing of float/integer literals

This commit is contained in:
Jeroen van Rijn
2026-03-07 12:38:04 +01:00
parent a6cfde4373
commit 6434bf4b65
3 changed files with 27 additions and 4 deletions

View File

@@ -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)

View File

@@ -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);
}

View File

@@ -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");