]> granicus.if.org Git - python/commitdiff
Fix #3651 various memory leaks when using the buffer interface
authorBenjamin Peterson <benjamin@python.org>
Wed, 27 Aug 2008 00:31:37 +0000 (00:31 +0000)
committerBenjamin Peterson <benjamin@python.org>
Wed, 27 Aug 2008 00:31:37 +0000 (00:31 +0000)
by Amaury Forgeot d'Arc
Reviewer: Antoine Pitrou

Include/object.h
Misc/NEWS
Modules/binascii.c
Objects/abstract.c
Python/getargs.c

index 60584a02c33615bab220b7a9898cbfa3605ba883..bddfb6fe3674b744fae774bd4a9ba0b383b567f4 100644 (file)
@@ -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.*/
index e001936c55b99ee1895a4be65260416913a2a6bb..3927f9b86b193f8d3c6fb503129ac6eb54901c7f 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -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.
 
index 82c14234c46a7a541e443fccefbe58ac8ee11410..c6e03620793245888b12b8ff73b18e6eae6a0d03 100644 (file)
@@ -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;
                }
index ac61011c82025dda665b911e1c285a47c8647ead..39cb8036140ff9fccc86e29a2f388012cbfcf07b 100644 (file)
@@ -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;
 }
 
index b7beb37c907340c3b6f44f8bc150d01f681719c3..13c3f4b9a6ef4dfe9241e15a4a0dd11ba92fd1eb 100644 (file)
@@ -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;
                }