Merged revisions 65654 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/trunk

........
  r65654 | martin.v.loewis | 2008-08-12 16:49:50 +0200 (Tue, 12 Aug 2008) | 6 lines

  Issue #3139: Make buffer-interface thread-safe wrt. PyArg_ParseTuple,
  by denying s# to parse objects that have a releasebuffer procedure,
  and introducing s*.

  More module might need to get converted to use s*.
........
diff --git a/Objects/abstract.c b/Objects/abstract.c
index f15883e..6b73aca 100644
--- a/Objects/abstract.c
+++ b/Objects/abstract.c
@@ -349,16 +349,6 @@
 	return (*(obj->ob_type->tp_as_buffer->bf_getbuffer))(obj, view, flags);
 }
 
-void
-PyObject_ReleaseBuffer(PyObject *obj, Py_buffer *view)
-{
-	if (obj->ob_type->tp_as_buffer != NULL &&
-	    obj->ob_type->tp_as_buffer->bf_releasebuffer != NULL) {
-		(*(obj->ob_type->tp_as_buffer->bf_releasebuffer))(obj, view);
-	}
-}
-
-
 static int
 _IsFortranContiguous(Py_buffer *view)
 {
@@ -590,15 +580,15 @@
 
 	if (PyObject_GetBuffer(dest, &view_dest, PyBUF_FULL) != 0) return -1;
 	if (PyObject_GetBuffer(src, &view_src, PyBUF_FULL_RO) != 0) {
-		PyObject_ReleaseBuffer(dest, &view_dest);
+		PyBuffer_Release(&view_dest);
 		return -1;
 	}
 
 	if (view_dest.len < view_src.len) {
 		PyErr_SetString(PyExc_BufferError,
 				"destination is too small to receive data from source");
-		PyObject_ReleaseBuffer(dest, &view_dest);
-		PyObject_ReleaseBuffer(src, &view_src);
+		PyBuffer_Release(&view_dest);
+		PyBuffer_Release(&view_src);
 		return -1;
 	}
 
@@ -608,8 +598,8 @@
 	     PyBuffer_IsContiguous(&view_src, 'F'))) {
 		/* simplest copy is all that is needed */
 		memcpy(view_dest.buf, view_src.buf, view_src.len);
-		PyObject_ReleaseBuffer(dest, &view_dest);
-		PyObject_ReleaseBuffer(src, &view_src);
+		PyBuffer_Release(&view_dest);
+		PyBuffer_Release(&view_src);
 		return 0;
 	}
 
@@ -619,8 +609,8 @@
 	indices = (Py_ssize_t *)PyMem_Malloc(sizeof(Py_ssize_t)*view_src.ndim);
 	if (indices == NULL) {
 		PyErr_NoMemory();
-		PyObject_ReleaseBuffer(dest, &view_dest);
-		PyObject_ReleaseBuffer(src, &view_src);
+		PyBuffer_Release(&view_dest);
+		PyBuffer_Release(&view_src);
 		return -1;
 	}
 	for (k=0; k<view_src.ndim;k++) {
@@ -638,8 +628,8 @@
 		memcpy(dptr, sptr, view_src.itemsize);
 	}
 	PyMem_Free(indices);
-	PyObject_ReleaseBuffer(dest, &view_dest);
-	PyObject_ReleaseBuffer(src, &view_src);
+	PyBuffer_Release(&view_dest);
+	PyBuffer_Release(&view_src);
 	return 0;
 }
 
@@ -668,7 +658,7 @@
 }
 
 int
-PyBuffer_FillInfo(Py_buffer *view, void *buf, Py_ssize_t len,
+PyBuffer_FillInfo(Py_buffer *view, PyObject *obj, void *buf, Py_ssize_t len,
 	      int readonly, int flags)
 {
 	if (view == NULL) return 0;
@@ -679,6 +669,7 @@
 		return -1;
 	}
 
+	view->obj = obj;
 	view->buf = buf;
 	view->len = len;
 	view->readonly = readonly;
@@ -698,6 +689,17 @@
 	return 0;
 }
 
+void
+PyBuffer_Release(Py_buffer *view)
+{
+	PyObject *obj = view->obj;
+	if (!obj || !Py_TYPE(obj)->tp_as_buffer || !Py_TYPE(obj)->tp_as_buffer->bf_releasebuffer)
+		/* Unmanaged buffer */
+		return;
+	Py_TYPE(obj)->tp_as_buffer->bf_releasebuffer(obj, view);
+	
+}
+
 PyObject *
 PyObject_Format(PyObject *obj, PyObject *format_spec)
 {