From 4f71a2a75a71b89dad2eed147d6e237b633b878e Mon Sep 17 00:00:00 2001 From: Jeff Epler <jepler@gmail.com> Date: Sat, 19 May 2018 10:56:34 -0500 Subject: [PATCH] py/parsenum: Avoid undefined behavior parsing floats with large exponents. Fuzz testing combined with the undefined behavior sanitizer found that parsing unreasonable float literals like 1e+9999999999999 resulted in undefined behavior due to overflow in signed integer arithmetic, and a wrong result being returned. --- py/parsenum.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/py/parsenum.c b/py/parsenum.c index 8bd5232eb4..ba7e40afd6 100644 --- a/py/parsenum.c +++ b/py/parsenum.c @@ -234,7 +234,12 @@ mp_obj_t mp_parse_num_decimal(const char *str, size_t len, bool allow_imag, bool if ('0' <= dig && dig <= '9') { dig -= '0'; if (in == PARSE_DEC_IN_EXP) { - exp_val = 10 * exp_val + dig; + // don't overflow exp_val when adding next digit, instead just truncate + // it and the resulting float will still be correct, either inf or 0.0 + // (use INT_MAX/2 to allow adding exp_extra at the end without overflow) + if (exp_val < (INT_MAX / 2 - 9) / 10) { + exp_val = 10 * exp_val + dig; + } } else { if (dec_val < DEC_VAL_MAX) { // dec_val won't overflow so keep accumulating