bpo-36262: Fix _Py_dg_strtod() memory leak (goto undfl) (GH-12276) (GH-12331)
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 9776b0636a
)
This commit is contained in:
parent
783bed4c8d
commit
9818360ed9
|
@ -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.
|
|
@ -1441,8 +1441,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.;
|
||||||
|
|
||||||
|
@ -1634,7 +1635,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
|
||||||
) {
|
) {
|
||||||
|
@ -1804,14 +1804,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
|
||||||
|
@ -1821,9 +1818,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1874,54 +1868,36 @@ _Py_dg_strtod(const char *s00, char **se)
|
||||||
if (bb5 > 0) {
|
if (bb5 > 0) {
|
||||||
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);
|
Bigint *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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1932,10 +1908,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;
|
||||||
|
@ -1989,10 +1961,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)
|
||||||
|
@ -2094,11 +2062,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;
|
||||||
|
@ -2140,16 +2103,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)
|
||||||
|
@ -2163,24 +2121,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;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue