[Python-3000-checkins] r66047 - in python/branches/py3k: Include/object.h Misc/NEWS Modules/binascii.c Objects/abstract.c Python/getargs.c

benjamin.peterson python-3000-checkins at python.org
Wed Aug 27 02:31:37 CEST 2008


Author: benjamin.peterson
Date: Wed Aug 27 02:31:37 2008
New Revision: 66047

Log:
Fix #3651  various memory leaks when using the buffer interface

by Amaury Forgeot d'Arc
Reviewer: Antoine Pitrou


Modified:
   python/branches/py3k/Include/object.h
   python/branches/py3k/Misc/NEWS
   python/branches/py3k/Modules/binascii.c
   python/branches/py3k/Objects/abstract.c
   python/branches/py3k/Python/getargs.c

Modified: python/branches/py3k/Include/object.h
==============================================================================
--- python/branches/py3k/Include/object.h	(original)
+++ python/branches/py3k/Include/object.h	Wed Aug 27 02:31:37 2008
@@ -143,7 +143,7 @@
 /* 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.*/

Modified: python/branches/py3k/Misc/NEWS
==============================================================================
--- python/branches/py3k/Misc/NEWS	(original)
+++ python/branches/py3k/Misc/NEWS	Wed Aug 27 02:31:37 2008
@@ -21,6 +21,10 @@
 
 - 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.
 

Modified: python/branches/py3k/Modules/binascii.c
==============================================================================
--- python/branches/py3k/Modules/binascii.c	(original)
+++ python/branches/py3k/Modules/binascii.c	Wed Aug 27 02:31:37 2008
@@ -231,6 +231,7 @@
 			*/
 			if ( this_ch < ' ' || this_ch > (' ' + 64)) {
 				PyErr_SetString(Error, "Illegal char");
+				PyBuffer_Release(&pascii);
 				Py_DECREF(rv);
 				return NULL;
 			}
@@ -259,6 +260,7 @@
 		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 @@
 			** 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;
 		}

Modified: python/branches/py3k/Objects/abstract.c
==============================================================================
--- python/branches/py3k/Objects/abstract.c	(original)
+++ python/branches/py3k/Objects/abstract.c	Wed Aug 27 02:31:37 2008
@@ -260,6 +260,7 @@
 	*buffer_len = view.len;
 	if (pb->bf_releasebuffer != NULL)
 		(*pb->bf_releasebuffer)(obj, &view);
+	Py_XDECREF(view.obj);
 	return 0;
 }
 
@@ -305,6 +306,7 @@
 	*buffer_len = view.len;
 	if (pb->bf_releasebuffer != NULL)
 		(*pb->bf_releasebuffer)(obj, &view);
+	Py_XDECREF(view.obj);
 	return 0;
 }
 
@@ -332,6 +334,7 @@
 	*buffer_len = view.len;
 	if (pb->bf_releasebuffer != NULL)
 		(*pb->bf_releasebuffer)(obj, &view);
+	Py_XDECREF(view.obj);
 	return 0;
 }
 

Modified: python/branches/py3k/Python/getargs.c
==============================================================================
--- python/branches/py3k/Python/getargs.c	(original)
+++ python/branches/py3k/Python/getargs.c	Wed Aug 27 02:31:37 2008
@@ -1245,7 +1245,7 @@
 			/* 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 @@
 		/* 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 @@
 				"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 @@
 				"string or pinned buffer",
 				arg, msgbuf, bufsize);
 
+		PyBuffer_Release(&view);
+
 		if (count < 0)
 			return converterr("(unspecified)", arg, msgbuf, bufsize);
 		{
@@ -1340,14 +1342,13 @@
 		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 @@
 		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;
 		}


More information about the Python-3000-checkins mailing list