diff --git a/Misc/NEWS.d/next/Core and Builtins/2019-03-11-15-37-33.bpo-36262.v3N6Fz.rst b/Misc/NEWS.d/next/Core and Builtins/2019-03-11-15-37-33.bpo-36262.v3N6Fz.rst new file mode 100644 index 00000000000..b5ccc95fd70 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2019-03-11-15-37-33.bpo-36262.v3N6Fz.rst @@ -0,0 +1,3 @@ +Fix an unlikely memory leak on conversion from string to float in the function +``_Py_dg_strtod()`` used by ``float(str)``, ``complex(str)``, +:func:`pickle.load`, :func:`marshal.load`, etc. diff --git a/Python/dtoa.c b/Python/dtoa.c index 01ca9b0b22f..b7bb7acfb6c 100644 --- a/Python/dtoa.c +++ b/Python/dtoa.c @@ -1441,8 +1441,9 @@ _Py_dg_strtod(const char *s00, char **se) ULong y, z, abs_exp; Long L; BCinfo bc; - Bigint *bb, *bb1, *bd, *bd0, *bs, *delta; + Bigint *bb = NULL, *bd = NULL, *bd0 = NULL, *bs = NULL, *delta = NULL; size_t ndigits, fraclen; + double result; dval(&rv) = 0.; @@ -1634,7 +1635,6 @@ _Py_dg_strtod(const char *s00, char **se) if (k > 9) { dval(&rv) = tens[k - 9] * dval(&rv) + z; } - bd0 = 0; if (nd <= DBL_DIG && Flt_Rounds == 1 ) { @@ -1804,14 +1804,11 @@ _Py_dg_strtod(const char *s00, char **se) bd = Balloc(bd0->k); if (bd == NULL) { - Bfree(bd0); goto failed_malloc; } Bcopy(bd, bd0); bb = sd2b(&rv, bc.scale, &bbe); /* srv = bb * 2^bbe */ if (bb == NULL) { - Bfree(bd); - Bfree(bd0); goto failed_malloc; } /* Record whether lsb of bb is odd, in case we need this @@ -1821,9 +1818,6 @@ _Py_dg_strtod(const char *s00, char **se) /* tdv = bd * 10**e; srv = bb * 2**bbe */ bs = i2b(1); if (bs == NULL) { - Bfree(bb); - Bfree(bd); - Bfree(bd0); goto failed_malloc; } @@ -1874,54 +1868,36 @@ _Py_dg_strtod(const char *s00, char **se) if (bb5 > 0) { bs = pow5mult(bs, bb5); if (bs == NULL) { - Bfree(bb); - Bfree(bd); - Bfree(bd0); goto failed_malloc; } - bb1 = mult(bs, bb); + Bigint *bb1 = mult(bs, bb); Bfree(bb); bb = bb1; if (bb == NULL) { - Bfree(bs); - Bfree(bd); - Bfree(bd0); goto failed_malloc; } } if (bb2 > 0) { bb = lshift(bb, bb2); if (bb == NULL) { - Bfree(bs); - Bfree(bd); - Bfree(bd0); goto failed_malloc; } } if (bd5 > 0) { bd = pow5mult(bd, bd5); if (bd == NULL) { - Bfree(bb); - Bfree(bs); - Bfree(bd0); goto failed_malloc; } } if (bd2 > 0) { bd = lshift(bd, bd2); if (bd == NULL) { - Bfree(bb); - Bfree(bs); - Bfree(bd0); goto failed_malloc; } } if (bs2 > 0) { bs = lshift(bs, bs2); if (bs == NULL) { - Bfree(bb); - Bfree(bd); - Bfree(bd0); goto failed_malloc; } } @@ -1932,10 +1908,6 @@ _Py_dg_strtod(const char *s00, char **se) delta = diff(bb, bd); if (delta == NULL) { - Bfree(bb); - Bfree(bs); - Bfree(bd); - Bfree(bd0); goto failed_malloc; } dsign = delta->sign; @@ -1989,10 +1961,6 @@ _Py_dg_strtod(const char *s00, char **se) } delta = lshift(delta,Log2P); if (delta == NULL) { - Bfree(bb); - Bfree(bs); - Bfree(bd); - Bfree(bd0); goto failed_malloc; } if (cmp(delta, bs) > 0) @@ -2094,11 +2062,6 @@ _Py_dg_strtod(const char *s00, char **se) if ((word0(&rv) & Exp_mask) >= Exp_msk1*(DBL_MAX_EXP+Bias-P)) { if (word0(&rv0) == Big0 && word1(&rv0) == Big1) { - Bfree(bb); - Bfree(bd); - Bfree(bs); - Bfree(bd0); - Bfree(delta); goto ovfl; } word0(&rv) = Big0; @@ -2140,16 +2103,11 @@ _Py_dg_strtod(const char *s00, char **se) } } cont: - Bfree(bb); - Bfree(bd); - Bfree(bs); - Bfree(delta); + Bfree(bb); bb = NULL; + Bfree(bd); bd = NULL; + Bfree(bs); bs = NULL; + Bfree(delta); delta = NULL; } - Bfree(bb); - Bfree(bd); - Bfree(bs); - Bfree(bd0); - Bfree(delta); if (bc.nd > nd) { error = bigcomp(&rv, s0, &bc); if (error) @@ -2163,24 +2121,37 @@ _Py_dg_strtod(const char *s00, char **se) } ret: - return sign ? -dval(&rv) : dval(&rv); + result = sign ? -dval(&rv) : dval(&rv); + goto done; parse_error: - return 0.0; + result = 0.0; + goto done; failed_malloc: errno = ENOMEM; - return -1.0; + result = -1.0; + goto done; undfl: - return sign ? -0.0 : 0.0; + result = sign ? -0.0 : 0.0; + goto done; ovfl: errno = ERANGE; /* Can't trust HUGE_VAL */ word0(&rv) = Exp_mask; word1(&rv) = 0; - return sign ? -dval(&rv) : dval(&rv); + result = sign ? -dval(&rv) : dval(&rv); + goto done; + + done: + Bfree(bb); + Bfree(bd); + Bfree(bs); + Bfree(bd0); + Bfree(delta); + return result; }