summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Oudkerk <shibturn@gmail.com>2013-07-15 15:05:22 (GMT)
committerRichard Oudkerk <shibturn@gmail.com>2013-07-15 15:05:22 (GMT)
commit9ad51ec81b4fd9e753f92b5d0c840e18c0762c40 (patch)
tree8b2689b64c3f0cf348c2337f9ee24fe071b17343
parent2670b9acb6daa7fe04f3c1e93beb9ad104f879e5 (diff)
downloadcpython-9ad51ec81b4fd9e753f92b5d0c840e18c0762c40.zip
cpython-9ad51ec81b4fd9e753f92b5d0c840e18c0762c40.tar.gz
cpython-9ad51ec81b4fd9e753f92b5d0c840e18c0762c40.tar.bz2
Issue #18344: Fix potential ref-leaks in _bufferedreader_read_all().
-rw-r--r--Misc/NEWS2
-rw-r--r--Modules/_io/bufferedio.c93
2 files changed, 47 insertions, 48 deletions
diff --git a/Misc/NEWS b/Misc/NEWS
index 6fb0994..56ebe91 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -12,6 +12,8 @@ What's New in Python 3.3.3 release candidate 1?
Core and Builtins
-----------------
+- Issue #18344: Fix potential ref-leaks in _bufferedreader_read_all().
+
- Issue #17872: Fix a segfault in marshal.load() when input stream returns
more bytes than requested.
diff --git a/Modules/_io/bufferedio.c b/Modules/_io/bufferedio.c
index 7f180a4..3afe7b1 100644
--- a/Modules/_io/bufferedio.c
+++ b/Modules/_io/bufferedio.c
@@ -1474,7 +1474,7 @@ static PyObject *
_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);
@@ -1487,85 +1487,82 @@ _bufferedreader_read_all(buffered *self)
}
/* 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.