Commit 96a0378e authored by Richard Oudkerk's avatar Richard Oudkerk

Issue #18344: Fix potential ref-leaks in _bufferedreader_read_all().

parent f744645c
...@@ -12,6 +12,8 @@ What's New in Python 3.3.3 release candidate 1? ...@@ -12,6 +12,8 @@ What's New in Python 3.3.3 release candidate 1?
Core and Builtins 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 - Issue #17872: Fix a segfault in marshal.load() when input stream returns
more bytes than requested. more bytes than requested.
......
...@@ -1474,7 +1474,7 @@ static PyObject * ...@@ -1474,7 +1474,7 @@ static PyObject *
_bufferedreader_read_all(buffered *self) _bufferedreader_read_all(buffered *self)
{ {
Py_ssize_t current_size; 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. */ /* First copy what we have in the current buffer. */
current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t); current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
...@@ -1487,85 +1487,82 @@ _bufferedreader_read_all(buffered *self) ...@@ -1487,85 +1487,82 @@ _bufferedreader_read_all(buffered *self)
} }
/* We're going past the buffer's bounds, flush it */ /* We're going past the buffer's bounds, flush it */
if (self->writable) { if (self->writable) {
res = buffered_flush_and_rewind_unlocked(self); tmp = buffered_flush_and_rewind_unlocked(self);
if (res == NULL) if (tmp == NULL)
return NULL; goto cleanup;
Py_CLEAR(res); Py_CLEAR(tmp);
} }
_bufferedreader_reset_buf(self); _bufferedreader_reset_buf(self);
if (PyObject_HasAttr(self->raw, _PyIO_str_readall)) { if (PyObject_HasAttr(self->raw, _PyIO_str_readall)) {
chunk = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_readall, NULL); tmp = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_readall, NULL);
if (chunk == NULL) if (tmp == NULL)
return NULL; goto cleanup;
if (chunk != Py_None && !PyBytes_Check(chunk)) { if (tmp != Py_None && !PyBytes_Check(tmp)) {
Py_XDECREF(data);
Py_DECREF(chunk);
PyErr_SetString(PyExc_TypeError, "readall() should return bytes"); PyErr_SetString(PyExc_TypeError, "readall() should return bytes");
return NULL; goto cleanup;
} }
if (chunk == Py_None) { if (tmp == Py_None) {
if (current_size == 0) if (current_size == 0) {
return chunk; res = Py_None;
else { goto cleanup;
Py_DECREF(chunk); } else {
return data; res = data;
goto cleanup;
} }
} }
else if (current_size) { else if (current_size) {
PyBytes_Concat(&data, chunk); PyBytes_Concat(&data, tmp);
Py_DECREF(chunk); res = data;
if (data == NULL) goto cleanup;
return NULL; }
return data; else {
} else res = tmp;
return chunk; goto cleanup;
}
} }
chunks = PyList_New(0); chunks = PyList_New(0);
if (chunks == NULL) { if (chunks == NULL)
Py_XDECREF(data); goto cleanup;
return NULL;
}
while (1) { while (1) {
if (data) { if (data) {
if (PyList_Append(chunks, data) < 0) { if (PyList_Append(chunks, data) < 0)
Py_DECREF(data); goto cleanup;
Py_DECREF(chunks); Py_CLEAR(data);
return NULL;
}
Py_DECREF(data);
} }
/* Read until EOF or until read() would block. */ /* Read until EOF or until read() would block. */
data = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_read, NULL); data = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_read, NULL);
if (data == NULL) { if (data == NULL)
Py_DECREF(chunks); goto cleanup;
return NULL;
}
if (data != Py_None && !PyBytes_Check(data)) { if (data != Py_None && !PyBytes_Check(data)) {
Py_DECREF(data);
Py_DECREF(chunks);
PyErr_SetString(PyExc_TypeError, "read() should return bytes"); PyErr_SetString(PyExc_TypeError, "read() should return bytes");
return NULL; goto cleanup;
} }
if (data == Py_None || PyBytes_GET_SIZE(data) == 0) { if (data == Py_None || PyBytes_GET_SIZE(data) == 0) {
if (current_size == 0) { if (current_size == 0) {
Py_DECREF(chunks); res = data;
return data; goto cleanup;
} }
else { else {
res = _PyBytes_Join(_PyIO_empty_bytes, chunks); tmp = _PyBytes_Join(_PyIO_empty_bytes, chunks);
Py_DECREF(data); res = tmp;
Py_DECREF(chunks); goto cleanup;
return res;
} }
} }
current_size += PyBytes_GET_SIZE(data); current_size += PyBytes_GET_SIZE(data);
if (self->abs_pos != -1) if (self->abs_pos != -1)
self->abs_pos += PyBytes_GET_SIZE(data); 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. /* Read n bytes from the buffer if it can, otherwise return None.
......
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