mirror of
https://github.com/python/cpython.git
synced 2025-07-25 20:24:11 +00:00
Issue #18344: Fix potential ref-leaks in _bufferedreader_read_all().
This commit is contained in:
commit
9ba6962a04
2 changed files with 47 additions and 48 deletions
|
@ -10,6 +10,8 @@ What's New in Python 3.4.0 Alpha 1?
|
||||||
Core and Builtins
|
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
|
- Issue #18342: Use the repr of a module name when an import fails when using
|
||||||
``from ... import ...``.
|
``from ... import ...``.
|
||||||
|
|
||||||
|
|
|
@ -1479,7 +1479,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);
|
||||||
|
@ -1492,85 +1492,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.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue