mirror of https://github.com/python/cpython
Fix #3651 various memory leaks when using the buffer interface
by Amaury Forgeot d'Arc Reviewer: Antoine Pitrou
This commit is contained in:
parent
4b24a42f3c
commit
9edd2bd35c
|
@ -143,7 +143,7 @@ typedef int(*objobjargproc)(PyObject *, PyObject *, PyObject *);
|
|||
/* buffer interface */
|
||||
typedef struct bufferinfo {
|
||||
void *buf;
|
||||
PyObject *obj; /* borrowed reference */
|
||||
PyObject *obj; /* owned reference */
|
||||
Py_ssize_t len;
|
||||
Py_ssize_t itemsize; /* This is Py_ssize_t so it can be
|
||||
pointed to by strides in simple case.*/
|
||||
|
|
|
@ -21,6 +21,10 @@ Core and Builtins
|
|||
|
||||
- Issue #3663: Py_None was decref'd when printing SyntaxErrors.
|
||||
|
||||
- Issue #3651: Fix various memory leaks when using the buffer
|
||||
interface, or when the "s#" code of PyArg_ParseTuple is given a
|
||||
bytes object.
|
||||
|
||||
- Issue #3657: Fix uninitialized memory read when pickling longs.
|
||||
Found by valgrind.
|
||||
|
||||
|
|
|
@ -231,6 +231,7 @@ binascii_a2b_uu(PyObject *self, PyObject *args)
|
|||
*/
|
||||
if ( this_ch < ' ' || this_ch > (' ' + 64)) {
|
||||
PyErr_SetString(Error, "Illegal char");
|
||||
PyBuffer_Release(&pascii);
|
||||
Py_DECREF(rv);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -259,6 +260,7 @@ binascii_a2b_uu(PyObject *self, PyObject *args)
|
|||
if ( this_ch != ' ' && this_ch != ' '+64 &&
|
||||
this_ch != '\n' && this_ch != '\r' ) {
|
||||
PyErr_SetString(Error, "Trailing garbage");
|
||||
PyBuffer_Release(&pascii);
|
||||
Py_DECREF(rv);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -805,6 +807,7 @@ binascii_rledecode_hqx(PyObject *self, PyObject *args)
|
|||
** of the string only). This is a programmer error.
|
||||
*/
|
||||
PyErr_SetString(Error, "Orphaned RLE code at start");
|
||||
PyBuffer_Release(&pin);
|
||||
Py_DECREF(rv);
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -260,6 +260,7 @@ PyObject_AsCharBuffer(PyObject *obj,
|
|||
*buffer_len = view.len;
|
||||
if (pb->bf_releasebuffer != NULL)
|
||||
(*pb->bf_releasebuffer)(obj, &view);
|
||||
Py_XDECREF(view.obj);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -305,6 +306,7 @@ int PyObject_AsReadBuffer(PyObject *obj,
|
|||
*buffer_len = view.len;
|
||||
if (pb->bf_releasebuffer != NULL)
|
||||
(*pb->bf_releasebuffer)(obj, &view);
|
||||
Py_XDECREF(view.obj);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -332,6 +334,7 @@ int PyObject_AsWriteBuffer(PyObject *obj,
|
|||
*buffer_len = view.len;
|
||||
if (pb->bf_releasebuffer != NULL)
|
||||
(*pb->bf_releasebuffer)(obj, &view);
|
||||
Py_XDECREF(view.obj);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -1245,7 +1245,7 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags,
|
|||
/* Caller is interested in Py_buffer, and the object
|
||||
supports it directly. */
|
||||
format++;
|
||||
if (pb->bf_getbuffer(arg, (Py_buffer*)p, PyBUF_WRITABLE) < 0) {
|
||||
if (PyObject_GetBuffer(arg, (Py_buffer*)p, PyBUF_WRITABLE) < 0) {
|
||||
PyErr_Clear();
|
||||
return converterr("read-write buffer", arg, msgbuf, bufsize);
|
||||
}
|
||||
|
@ -1257,11 +1257,11 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags,
|
|||
/* Here we have processed w*, only w and w# remain. */
|
||||
if (pb == NULL ||
|
||||
pb->bf_getbuffer == NULL ||
|
||||
((temp = (*pb->bf_getbuffer)(arg, &view,
|
||||
PyBUF_SIMPLE)) != 0) ||
|
||||
((temp = PyObject_GetBuffer(arg, &view,
|
||||
PyBUF_SIMPLE)) != 0) ||
|
||||
view.readonly == 1) {
|
||||
if (temp==0 && pb->bf_releasebuffer != NULL) {
|
||||
(*pb->bf_releasebuffer)(arg, &view);
|
||||
if (temp==0) {
|
||||
PyBuffer_Release(&view);
|
||||
}
|
||||
return converterr("single-segment read-write buffer",
|
||||
arg, msgbuf, bufsize);
|
||||
|
@ -1295,7 +1295,7 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags,
|
|||
"bytes or read-only character buffer",
|
||||
arg, msgbuf, bufsize);
|
||||
|
||||
if ((*pb->bf_getbuffer)(arg, &view, PyBUF_SIMPLE) != 0)
|
||||
if (PyObject_GetBuffer(arg, &view, PyBUF_SIMPLE) != 0)
|
||||
return converterr("string or single-segment read-only buffer",
|
||||
arg, msgbuf, bufsize);
|
||||
|
||||
|
@ -1306,6 +1306,8 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags,
|
|||
"string or pinned buffer",
|
||||
arg, msgbuf, bufsize);
|
||||
|
||||
PyBuffer_Release(&view);
|
||||
|
||||
if (count < 0)
|
||||
return converterr("(unspecified)", arg, msgbuf, bufsize);
|
||||
{
|
||||
|
@ -1340,14 +1342,13 @@ convertbuffer(PyObject *arg, void **p, char **errmsg)
|
|||
return -1;
|
||||
}
|
||||
|
||||
if ((*pb->bf_getbuffer)(arg, &view, PyBUF_SIMPLE) != 0) {
|
||||
if (PyObject_GetBuffer(arg, &view, PyBUF_SIMPLE) != 0) {
|
||||
*errmsg = "bytes or single-segment read-only buffer";
|
||||
return -1;
|
||||
}
|
||||
count = view.len;
|
||||
*p = view.buf;
|
||||
if (pb->bf_releasebuffer != NULL)
|
||||
(*pb->bf_releasebuffer)(arg, &view);
|
||||
PyBuffer_Release(&view);
|
||||
return count;
|
||||
}
|
||||
|
||||
|
@ -1364,7 +1365,7 @@ getbuffer(PyObject *arg, Py_buffer *view, char **errmsg)
|
|||
return -1;
|
||||
}
|
||||
if (pb->bf_getbuffer) {
|
||||
if (pb->bf_getbuffer(arg, view, 0) < 0) {
|
||||
if (PyObject_GetBuffer(arg, view, 0) < 0) {
|
||||
*errmsg = "convertible to a buffer";
|
||||
return -1;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue