[Python-checkins] cpython (merge 3.3 -> default): Issue #18344: Fix potential ref-leaks in _bufferedreader_read_all().

richard.oudkerk python-checkins at python.org
Mon Jul 15 17:11:32 CEST 2013


http://hg.python.org/cpython/rev/9b041f44cb63
changeset:   84631:9b041f44cb63
parent:      84629:13b8fd71db46
parent:      84630:9ce863993a38
user:        Richard Oudkerk <shibturn at gmail.com>
date:        Mon Jul 15 16:10:28 2013 +0100
summary:
  Issue #18344: Fix potential ref-leaks in _bufferedreader_read_all().

files:
  Misc/NEWS                |   2 +
  Modules/_io/bufferedio.c |  93 +++++++++++++--------------
  2 files changed, 47 insertions(+), 48 deletions(-)


diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -10,6 +10,8 @@
 Core and Builtins
 -----------------
 
+- Issue #18344: Fix potential ref-leaks in _bufferedreader_read_all().
+
 - Issue #18342: Use the repr of a module name when an import fails when using
   ``from ... import ...``.
 
diff --git a/Modules/_io/bufferedio.c b/Modules/_io/bufferedio.c
--- a/Modules/_io/bufferedio.c
+++ b/Modules/_io/bufferedio.c
@@ -1479,7 +1479,7 @@
 _bufferedreader_read_all(buffered *self)
 {
     Py_ssize_t current_size;
-    PyObject *res, *data = NULL, *chunk, *chunks;
+    PyObject *res = NULL, *data = NULL, *tmp = NULL, *chunks = NULL;
 
     /* First copy what we have in the current buffer. */
     current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
@@ -1492,85 +1492,82 @@
     }
     /* We're going past the buffer's bounds, flush it */
     if (self->writable) {
-        res = buffered_flush_and_rewind_unlocked(self);
-        if (res == NULL)
-            return NULL;
-        Py_CLEAR(res);
+        tmp = buffered_flush_and_rewind_unlocked(self);
+        if (tmp == NULL)
+            goto cleanup;
+        Py_CLEAR(tmp);
     }
     _bufferedreader_reset_buf(self);
 
     if (PyObject_HasAttr(self->raw, _PyIO_str_readall)) {
-        chunk = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_readall, NULL);
-        if (chunk == NULL)
-            return NULL;
-        if (chunk != Py_None && !PyBytes_Check(chunk)) {
-            Py_XDECREF(data);
-            Py_DECREF(chunk);
+        tmp = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_readall, NULL);
+        if (tmp == NULL)
+            goto cleanup;
+        if (tmp != Py_None && !PyBytes_Check(tmp)) {
             PyErr_SetString(PyExc_TypeError, "readall() should return bytes");
-            return NULL;
+            goto cleanup;
         }
-        if (chunk == Py_None) {
-            if (current_size == 0)
-                return chunk;
-            else {
-                Py_DECREF(chunk);
-                return data;
+        if (tmp == Py_None) {
+            if (current_size == 0) {
+                res = Py_None;
+                goto cleanup;
+            } else {
+                res = data;
+                goto cleanup;
             }
         }
         else if (current_size) {
-            PyBytes_Concat(&data, chunk);
-            Py_DECREF(chunk);
-            if (data == NULL)
-                return NULL;
-            return data;
-        } else
-            return chunk;
+            PyBytes_Concat(&data, tmp);
+            res = data;
+            goto cleanup;
+        }
+        else {
+            res = tmp;
+            goto cleanup;
+        }
     }
 
     chunks = PyList_New(0);
-    if (chunks == NULL) {
-        Py_XDECREF(data);
-        return NULL;
-    }
+    if (chunks == NULL)
+        goto cleanup;
 
     while (1) {
         if (data) {
-            if (PyList_Append(chunks, data) < 0) {
-                Py_DECREF(data);
-                Py_DECREF(chunks);
-                return NULL;
-            }
-            Py_DECREF(data);
+            if (PyList_Append(chunks, data) < 0)
+                goto cleanup;
+            Py_CLEAR(data);
         }
 
         /* Read until EOF or until read() would block. */
         data = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_read, NULL);
-        if (data == NULL) {
-            Py_DECREF(chunks);
-            return NULL;
-        }
+        if (data == NULL)
+            goto cleanup;
         if (data != Py_None && !PyBytes_Check(data)) {
-            Py_DECREF(data);
-            Py_DECREF(chunks);
             PyErr_SetString(PyExc_TypeError, "read() should return bytes");
-            return NULL;
+            goto cleanup;
         }
         if (data == Py_None || PyBytes_GET_SIZE(data) == 0) {
             if (current_size == 0) {
-                Py_DECREF(chunks);
-                return data;
+                res = data;
+                goto cleanup;
             }
             else {
-                res = _PyBytes_Join(_PyIO_empty_bytes, chunks);
-                Py_DECREF(data);
-                Py_DECREF(chunks);
-                return res;
+                tmp = _PyBytes_Join(_PyIO_empty_bytes, chunks);
+                res = tmp;
+                goto cleanup;
             }
         }
         current_size += PyBytes_GET_SIZE(data);
         if (self->abs_pos != -1)
             self->abs_pos += PyBytes_GET_SIZE(data);
     }
+cleanup:
+    /* res is either NULL or a borrowed ref */
+    Py_XINCREF(res);
+    Py_XDECREF(data);
+    Py_XDECREF(tmp);
+    Py_XDECREF(chunks);
+    return res;
 }
 
 /* Read n bytes from the buffer if it can, otherwise return None.

-- 
Repository URL: http://hg.python.org/cpython


More information about the Python-checkins mailing list