aboutsummaryrefslogtreecommitdiff
path: root/py/parsenum.c
diff options
context:
space:
mode:
authorJeff Epler <jepler@gmail.com>2018-05-19 10:56:34 -0500
committerDamien George <damien.p.george@gmail.com>2018-05-21 12:37:57 +1000
commit4f71a2a75a71b89dad2eed147d6e237b633b878e (patch)
treedf59b91fe3299dbe213a9bdd31875ab790df55f1 /py/parsenum.c
parent5efc575067df17be785d2b60124706d789d6cfe0 (diff)
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.
Diffstat (limited to 'py/parsenum.c')
-rw-r--r--py/parsenum.c7
1 files changed, 6 insertions, 1 deletions
diff --git a/py/parsenum.c b/py/parsenum.c
index 8bd5232eb..ba7e40afd 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