py/parsenum: Fix parsing LLONG_MIN in longlong configuration.
Re-organize `mp_parse_num_integer()` (for longlong) slightly so that the most negative 64-bit integer can be parsed. Fixes issue #17932. Signed-off-by: Jeff Epler <jepler@gmail.com>
This commit is contained in:
parent
f4f7fbf3dc
commit
1671977ca4
3 changed files with 15 additions and 4 deletions
|
|
@ -247,7 +247,7 @@ char *mp_obj_int_formatted(char **buf, size_t *buf_size, size_t *fmt_size, mp_co
|
||||||
|
|
||||||
char sign = '\0';
|
char sign = '\0';
|
||||||
if (num < 0) {
|
if (num < 0) {
|
||||||
num = -num;
|
num = -(fmt_uint_t)num;
|
||||||
sign = '-';
|
sign = '-';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -64,7 +64,7 @@ typedef mp_int_t parsed_int_t;
|
||||||
typedef unsigned long long parsed_int_t;
|
typedef unsigned long long parsed_int_t;
|
||||||
|
|
||||||
#define PARSED_INT_MUL_OVERFLOW mp_mul_ull_overflow
|
#define PARSED_INT_MUL_OVERFLOW mp_mul_ull_overflow
|
||||||
#define PARSED_INT_FITS(I) ((I) <= (unsigned long long)LLONG_MAX)
|
#define PARSED_INT_FITS(I) ((I) <= (unsigned long long)LLONG_MAX + 1)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
mp_obj_t mp_parse_num_integer(const char *restrict str_, size_t len, int base, mp_lexer_t *lex) {
|
mp_obj_t mp_parse_num_integer(const char *restrict str_, size_t len, int base, mp_lexer_t *lex) {
|
||||||
|
|
@ -135,8 +135,11 @@ mp_obj_t mp_parse_num_integer(const char *restrict str_, size_t len, int base, m
|
||||||
have_ret_val:
|
have_ret_val:
|
||||||
#else
|
#else
|
||||||
// The PARSED_INT_FITS check above ensures parsed_val won't overflow signed long long
|
// The PARSED_INT_FITS check above ensures parsed_val won't overflow signed long long
|
||||||
long long signed_val = parsed_val;
|
long long signed_val = -parsed_val;
|
||||||
if (neg) {
|
if (!neg) {
|
||||||
|
if (signed_val == LLONG_MIN) {
|
||||||
|
goto overflow;
|
||||||
|
}
|
||||||
signed_val = -signed_val;
|
signed_val = -signed_val;
|
||||||
}
|
}
|
||||||
ret_val = mp_obj_new_int_from_ll(signed_val); // Could be large or small int
|
ret_val = mp_obj_new_int_from_ll(signed_val); // Could be large or small int
|
||||||
|
|
|
||||||
|
|
@ -151,3 +151,11 @@ try:
|
||||||
print((1 << 48) << -6)
|
print((1 << 48) << -6)
|
||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
print(e)
|
print(e)
|
||||||
|
|
||||||
|
# Test that the most extreme 64 bit integer values all parse with int()
|
||||||
|
print(int("-9223372036854775807"))
|
||||||
|
print(int("-9223372036854775808"))
|
||||||
|
print(int("9223372036854775807"))
|
||||||
|
|
||||||
|
# Test that the most negative 64 bit integer can be formed via arithmetic
|
||||||
|
print(-9223372036854775807-1)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue