[Python-checkins] bpo-36262: Fix _Py_dg_strtod() memory leak (goto undfl) (GH-12276)

Victor Stinner webhook-mailer at python.org
Wed Mar 13 12:55:12 EDT 2019


https://github.com/python/cpython/commit/9776b0636ae39668d3ce1c006d4be01dad01bf9f
commit: 9776b0636ae39668d3ce1c006d4be01dad01bf9f
branch: master
author: Victor Stinner <vstinner at redhat.com>
committer: GitHub <noreply at github.com>
date: 2019-03-13T17:55:01+01:00
summary:

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

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.

files:
A Misc/NEWS.d/next/Core and Builtins/2019-03-11-15-37-33.bpo-36262.v3N6Fz.rst
M Python/dtoa.c

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 000000000000..b5ccc95fd705
--- /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 01ca9b0b22fb..b7bb7acfb6c2 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;
 
 }
 



More information about the Python-checkins mailing list