Commit b1405787 authored by Victor Stinner's avatar Victor Stinner Committed by GitHub

bpo-36262: Fix _Py_dg_strtod() memory leak (goto undfl) (GH-12276) (GH-12332)

Fix an unlikely memory leak on conversion from string to float in the
function _Py_dg_strtod() used by float(str), complex(str),
pickle.load(), marshal.load(), etc.

Fix an unlikely memory leak in _Py_dg_strtod() on "undfl:" label:
rewrite memory management in this function to always release all
memory before exiting the function. Initialize variables to NULL, and
set them to NULL after calling Bfree() at the "cont:" label.

Note: Bfree(NULL) is well defined: it does nothing.

(cherry picked from commit 9776b063)
parent 2dd6e079
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.
...@@ -1514,8 +1514,9 @@ _Py_dg_strtod(const char *s00, char **se) ...@@ -1514,8 +1514,9 @@ _Py_dg_strtod(const char *s00, char **se)
ULong y, z, abs_exp; ULong y, z, abs_exp;
Long L; Long L;
BCinfo bc; BCinfo bc;
Bigint *bb, *bb1, *bd, *bd0, *bs, *delta; Bigint *bb = NULL, *bd = NULL, *bd0 = NULL, *bs = NULL, *delta = NULL;
size_t ndigits, fraclen; size_t ndigits, fraclen;
double result;
dval(&rv) = 0.; dval(&rv) = 0.;
...@@ -1707,7 +1708,6 @@ _Py_dg_strtod(const char *s00, char **se) ...@@ -1707,7 +1708,6 @@ _Py_dg_strtod(const char *s00, char **se)
if (k > 9) { if (k > 9) {
dval(&rv) = tens[k - 9] * dval(&rv) + z; dval(&rv) = tens[k - 9] * dval(&rv) + z;
} }
bd0 = 0;
if (nd <= DBL_DIG if (nd <= DBL_DIG
&& Flt_Rounds == 1 && Flt_Rounds == 1
) { ) {
...@@ -1877,14 +1877,11 @@ _Py_dg_strtod(const char *s00, char **se) ...@@ -1877,14 +1877,11 @@ _Py_dg_strtod(const char *s00, char **se)
bd = Balloc(bd0->k); bd = Balloc(bd0->k);
if (bd == NULL) { if (bd == NULL) {
Bfree(bd0);
goto failed_malloc; goto failed_malloc;
} }
Bcopy(bd, bd0); Bcopy(bd, bd0);
bb = sd2b(&rv, bc.scale, &bbe); /* srv = bb * 2^bbe */ bb = sd2b(&rv, bc.scale, &bbe); /* srv = bb * 2^bbe */
if (bb == NULL) { if (bb == NULL) {
Bfree(bd);
Bfree(bd0);
goto failed_malloc; goto failed_malloc;
} }
/* Record whether lsb of bb is odd, in case we need this /* Record whether lsb of bb is odd, in case we need this
...@@ -1894,9 +1891,6 @@ _Py_dg_strtod(const char *s00, char **se) ...@@ -1894,9 +1891,6 @@ _Py_dg_strtod(const char *s00, char **se)
/* tdv = bd * 10**e; srv = bb * 2**bbe */ /* tdv = bd * 10**e; srv = bb * 2**bbe */
bs = i2b(1); bs = i2b(1);
if (bs == NULL) { if (bs == NULL) {
Bfree(bb);
Bfree(bd);
Bfree(bd0);
goto failed_malloc; goto failed_malloc;
} }
...@@ -1945,56 +1939,39 @@ _Py_dg_strtod(const char *s00, char **se) ...@@ -1945,56 +1939,39 @@ _Py_dg_strtod(const char *s00, char **se)
/* Scale bb, bd, bs by the appropriate powers of 2 and 5. */ /* Scale bb, bd, bs by the appropriate powers of 2 and 5. */
if (bb5 > 0) { if (bb5 > 0) {
Bigint *bb1;
bs = pow5mult(bs, bb5); bs = pow5mult(bs, bb5);
if (bs == NULL) { if (bs == NULL) {
Bfree(bb);
Bfree(bd);
Bfree(bd0);
goto failed_malloc; goto failed_malloc;
} }
bb1 = mult(bs, bb); bb1 = mult(bs, bb);
Bfree(bb); Bfree(bb);
bb = bb1; bb = bb1;
if (bb == NULL) { if (bb == NULL) {
Bfree(bs);
Bfree(bd);
Bfree(bd0);
goto failed_malloc; goto failed_malloc;
} }
} }
if (bb2 > 0) { if (bb2 > 0) {
bb = lshift(bb, bb2); bb = lshift(bb, bb2);
if (bb == NULL) { if (bb == NULL) {
Bfree(bs);
Bfree(bd);
Bfree(bd0);
goto failed_malloc; goto failed_malloc;
} }
} }
if (bd5 > 0) { if (bd5 > 0) {
bd = pow5mult(bd, bd5); bd = pow5mult(bd, bd5);
if (bd == NULL) { if (bd == NULL) {
Bfree(bb);
Bfree(bs);
Bfree(bd0);
goto failed_malloc; goto failed_malloc;
} }
} }
if (bd2 > 0) { if (bd2 > 0) {
bd = lshift(bd, bd2); bd = lshift(bd, bd2);
if (bd == NULL) { if (bd == NULL) {
Bfree(bb);
Bfree(bs);
Bfree(bd0);
goto failed_malloc; goto failed_malloc;
} }
} }
if (bs2 > 0) { if (bs2 > 0) {
bs = lshift(bs, bs2); bs = lshift(bs, bs2);
if (bs == NULL) { if (bs == NULL) {
Bfree(bb);
Bfree(bd);
Bfree(bd0);
goto failed_malloc; goto failed_malloc;
} }
} }
...@@ -2005,10 +1982,6 @@ _Py_dg_strtod(const char *s00, char **se) ...@@ -2005,10 +1982,6 @@ _Py_dg_strtod(const char *s00, char **se)
delta = diff(bb, bd); delta = diff(bb, bd);
if (delta == NULL) { if (delta == NULL) {
Bfree(bb);
Bfree(bs);
Bfree(bd);
Bfree(bd0);
goto failed_malloc; goto failed_malloc;
} }
dsign = delta->sign; dsign = delta->sign;
...@@ -2062,10 +2035,6 @@ _Py_dg_strtod(const char *s00, char **se) ...@@ -2062,10 +2035,6 @@ _Py_dg_strtod(const char *s00, char **se)
} }
delta = lshift(delta,Log2P); delta = lshift(delta,Log2P);
if (delta == NULL) { if (delta == NULL) {
Bfree(bb);
Bfree(bs);
Bfree(bd);
Bfree(bd0);
goto failed_malloc; goto failed_malloc;
} }
if (cmp(delta, bs) > 0) if (cmp(delta, bs) > 0)
...@@ -2167,11 +2136,6 @@ _Py_dg_strtod(const char *s00, char **se) ...@@ -2167,11 +2136,6 @@ _Py_dg_strtod(const char *s00, char **se)
if ((word0(&rv) & Exp_mask) >= if ((word0(&rv) & Exp_mask) >=
Exp_msk1*(DBL_MAX_EXP+Bias-P)) { Exp_msk1*(DBL_MAX_EXP+Bias-P)) {
if (word0(&rv0) == Big0 && word1(&rv0) == Big1) { if (word0(&rv0) == Big0 && word1(&rv0) == Big1) {
Bfree(bb);
Bfree(bd);
Bfree(bs);
Bfree(bd0);
Bfree(delta);
goto ovfl; goto ovfl;
} }
word0(&rv) = Big0; word0(&rv) = Big0;
...@@ -2213,16 +2177,11 @@ _Py_dg_strtod(const char *s00, char **se) ...@@ -2213,16 +2177,11 @@ _Py_dg_strtod(const char *s00, char **se)
} }
} }
cont: cont:
Bfree(bb); Bfree(bb); bb = NULL;
Bfree(bd); Bfree(bd); bd = NULL;
Bfree(bs); Bfree(bs); bs = NULL;
Bfree(delta); Bfree(delta); delta = NULL;
} }
Bfree(bb);
Bfree(bd);
Bfree(bs);
Bfree(bd0);
Bfree(delta);
if (bc.nd > nd) { if (bc.nd > nd) {
error = bigcomp(&rv, s0, &bc); error = bigcomp(&rv, s0, &bc);
if (error) if (error)
...@@ -2236,24 +2195,37 @@ _Py_dg_strtod(const char *s00, char **se) ...@@ -2236,24 +2195,37 @@ _Py_dg_strtod(const char *s00, char **se)
} }
ret: ret:
return sign ? -dval(&rv) : dval(&rv); result = sign ? -dval(&rv) : dval(&rv);
goto done;
parse_error: parse_error:
return 0.0; result = 0.0;
goto done;
failed_malloc: failed_malloc:
errno = ENOMEM; errno = ENOMEM;
return -1.0; result = -1.0;
goto done;
undfl: undfl:
return sign ? -0.0 : 0.0; result = sign ? -0.0 : 0.0;
goto done;
ovfl: ovfl:
errno = ERANGE; errno = ERANGE;
/* Can't trust HUGE_VAL */ /* Can't trust HUGE_VAL */
word0(&rv) = Exp_mask; word0(&rv) = Exp_mask;
word1(&rv) = 0; 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;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment