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