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)
 {
diff --git a/Objects/bytearrayobject.c b/Objects/bytearrayobject.c
index a76f827..dfe0a86 100644
--- a/Objects/bytearrayobject.c
+++ b/Objects/bytearrayobject.c
@@ -69,7 +69,7 @@
         ptr = "";
     else
         ptr = obj->ob_bytes;
-    ret = PyBuffer_FillInfo(view, ptr, Py_SIZE(obj), 0, flags);
+    ret = PyBuffer_FillInfo(view, (PyObject*)obj, ptr, Py_SIZE(obj), 0, flags);
     if (ret >= 0) {
         obj->ob_exports++;
     }
@@ -248,9 +248,9 @@
 
   done:
     if (va.len != -1)
-        PyObject_ReleaseBuffer(a, &va);
+        PyBuffer_Release(&va);
     if (vb.len != -1)
-        PyObject_ReleaseBuffer(b, &vb);
+        PyBuffer_Release(&vb);
     return (PyObject *)result;
 }
 
@@ -278,7 +278,7 @@
     mysize = Py_SIZE(self);
     size = mysize + vo.len;
     if (size < 0) {
-        PyObject_ReleaseBuffer(other, &vo);
+        PyBuffer_Release(&vo);
         return PyErr_NoMemory();
     }
     if (size < self->ob_alloc) {
@@ -286,11 +286,11 @@
         self->ob_bytes[Py_SIZE(self)] = '\0'; /* Trailing null byte */
     }
     else if (PyByteArray_Resize((PyObject *)self, size) < 0) {
-        PyObject_ReleaseBuffer(other, &vo);
+        PyBuffer_Release(&vo);
         return NULL;
     }
     memcpy(self->ob_bytes + mysize, vo.buf, vo.len);
-    PyObject_ReleaseBuffer(other, &vo);
+    PyBuffer_Release(&vo);
     Py_INCREF(self);
     return (PyObject *)self;
 }
@@ -501,7 +501,7 @@
 
  finish:
     if (vbytes.len != -1)
-            PyObject_ReleaseBuffer(values, &vbytes);
+            PyBuffer_Release(&vbytes);
     return res;
 }
 
@@ -767,10 +767,10 @@
         if (PyByteArray_Resize((PyObject *)self, size) < 0) goto fail;
         if (PyBuffer_ToContiguous(self->ob_bytes, &view, size, 'C') < 0)
                 goto fail;
-        PyObject_ReleaseBuffer(arg, &view);
+        PyBuffer_Release(&view);
         return 0;
     fail:
-        PyObject_ReleaseBuffer(arg, &view);
+        PyBuffer_Release(&view);
         return -1;
     }
 
@@ -954,7 +954,7 @@
     other_size = _getbuffer(other, &other_bytes);
     if (other_size < 0) {
         PyErr_Clear();
-        PyObject_ReleaseBuffer(self, &self_bytes);
+        PyBuffer_Release(&self_bytes);
         Py_INCREF(Py_NotImplemented);
         return Py_NotImplemented;
     }
@@ -989,8 +989,8 @@
     }
 
     res = cmp ? Py_True : Py_False;
-    PyObject_ReleaseBuffer(self, &self_bytes);
-    PyObject_ReleaseBuffer(other, &other_bytes);
+    PyBuffer_Release(&self_bytes);
+    PyBuffer_Release(&other_bytes);
     Py_INCREF(res);
     return res;
 }
@@ -998,6 +998,11 @@
 static void
 bytes_dealloc(PyByteArrayObject *self)
 {
+	if (self->ob_exports > 0) {
+		PyErr_SetString(PyExc_SystemError,
+			"deallocated bytearray object has exported buffers");
+		PyErr_Print();
+	}
     if (self->ob_bytes != 0) {
         PyMem_Free(self->ob_bytes);
     }
@@ -1065,7 +1070,7 @@
         res = stringlib_rfind_slice(
             PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self),
             subbuf.buf, subbuf.len, start, end);
-    PyObject_ReleaseBuffer(subobj, &subbuf);
+    PyBuffer_Release(&subbuf);
     return res;
 }
 
@@ -1115,7 +1120,7 @@
     count_obj = PyLong_FromSsize_t(
         stringlib_count(str + start, end - start, vsub.buf, vsub.len)
         );
-    PyObject_ReleaseBuffer(sub_obj, &vsub);
+    PyBuffer_Release(&vsub);
     return count_obj;
 }
 
@@ -1191,7 +1196,7 @@
             return -1;
         pos = stringlib_find(PyByteArray_AS_STRING(self), Py_SIZE(self),
                              varg.buf, varg.len, 0);
-        PyObject_ReleaseBuffer(arg, &varg);
+        PyBuffer_Release(&varg);
         return pos >= 0;
     }
     if (ival < 0 || ival >= 256) {
@@ -1241,7 +1246,7 @@
         rv = ! memcmp(str+start, vsubstr.buf, vsubstr.len);
 
 done:
-    PyObject_ReleaseBuffer(substr, &vsubstr);
+    PyBuffer_Release(&vsubstr);
     return rv;
 }
 
@@ -1421,9 +1426,9 @@
         PyByteArray_Resize(result, output - output_start);
 
 done:
-    PyObject_ReleaseBuffer(tableobj, &vtable);
+    PyBuffer_Release(&vtable);
     if (delobj != NULL)
-        PyObject_ReleaseBuffer(delobj, &vdel);
+        PyBuffer_Release(&vdel);
     return result;
 }
 
@@ -2042,7 +2047,7 @@
     if (_getbuffer(from, &vfrom) < 0)
         return NULL;
     if (_getbuffer(to, &vto) < 0) {
-        PyObject_ReleaseBuffer(from, &vfrom);
+        PyBuffer_Release(&vfrom);
         return NULL;
     }
 
@@ -2050,8 +2055,8 @@
                               vfrom.buf, vfrom.len,
                               vto.buf, vto.len, count);
 
-    PyObject_ReleaseBuffer(from, &vfrom);
-    PyObject_ReleaseBuffer(to, &vto);
+    PyBuffer_Release(&vfrom);
+    PyBuffer_Release(&vto);
     return res;
 }
 
@@ -2207,7 +2212,7 @@
 
     if (n == 0) {
         PyErr_SetString(PyExc_ValueError, "empty separator");
-        PyObject_ReleaseBuffer(subobj, &vsub);
+        PyBuffer_Release(&vsub);
         return NULL;
     }
     if (n == 1)
@@ -2215,7 +2220,7 @@
 
     list = PyList_New(PREALLOC_SIZE(maxsplit));
     if (list == NULL) {
-        PyObject_ReleaseBuffer(subobj, &vsub);
+        PyBuffer_Release(&vsub);
         return NULL;
     }
 
@@ -2243,12 +2248,12 @@
 #endif
     SPLIT_ADD(s, i, len);
     FIX_PREALLOC_SIZE(list);
-    PyObject_ReleaseBuffer(subobj, &vsub);
+    PyBuffer_Release(&vsub);
     return list;
 
   onError:
     Py_DECREF(list);
-    PyObject_ReleaseBuffer(subobj, &vsub);
+    PyBuffer_Release(&vsub);
     return NULL;
 }
 
@@ -2439,7 +2444,7 @@
 
     if (n == 0) {
         PyErr_SetString(PyExc_ValueError, "empty separator");
-        PyObject_ReleaseBuffer(subobj, &vsub);
+        PyBuffer_Release(&vsub);
         return NULL;
     }
     else if (n == 1)
@@ -2447,7 +2452,7 @@
 
     list = PyList_New(PREALLOC_SIZE(maxsplit));
     if (list == NULL) {
-        PyObject_ReleaseBuffer(subobj, &vsub);
+        PyBuffer_Release(&vsub);
         return NULL;
     }
 
@@ -2468,12 +2473,12 @@
     FIX_PREALLOC_SIZE(list);
     if (PyList_Reverse(list) < 0)
         goto onError;
-    PyObject_ReleaseBuffer(subobj, &vsub);
+    PyBuffer_Release(&vsub);
     return list;
 
 onError:
     Py_DECREF(list);
-    PyObject_ReleaseBuffer(subobj, &vsub);
+    PyBuffer_Release(&vsub);
     return NULL;
 }
 
@@ -2749,7 +2754,7 @@
     else
         right = rstrip_helper(myptr, mysize, argptr, argsize);
     if (arg != Py_None)
-        PyObject_ReleaseBuffer(arg, &varg);
+        PyBuffer_Release(&varg);
     return PyByteArray_FromStringAndSize(self->ob_bytes + left, right - left);
 }
 
@@ -2783,7 +2788,7 @@
     left = lstrip_helper(myptr, mysize, argptr, argsize);
     right = mysize;
     if (arg != Py_None)
-        PyObject_ReleaseBuffer(arg, &varg);
+        PyBuffer_Release(&varg);
     return PyByteArray_FromStringAndSize(self->ob_bytes + left, right - left);
 }
 
@@ -2817,7 +2822,7 @@
     left = 0;
     right = rstrip_helper(myptr, mysize, argptr, argsize);
     if (arg != Py_None)
-        PyObject_ReleaseBuffer(arg, &varg);
+        PyBuffer_Release(&varg);
     return PyByteArray_FromStringAndSize(self->ob_bytes + left, right - left);
 }
 
diff --git a/Objects/bytesobject.c b/Objects/bytesobject.c
index 7c1469c..52479ca 100644
--- a/Objects/bytesobject.c
+++ b/Objects/bytesobject.c
@@ -710,9 +710,9 @@
 
   done:
 	if (va.len != -1)
-		PyObject_ReleaseBuffer(a, &va);
+		PyBuffer_Release(&va);
 	if (vb.len != -1)
-		PyObject_ReleaseBuffer(b, &vb);
+		PyBuffer_Release(&vb);
 	return result;
 }
 
@@ -781,7 +781,7 @@
             return -1;
         pos = stringlib_find(PyBytes_AS_STRING(self), Py_SIZE(self),
                              varg.buf, varg.len, 0);
-        PyObject_ReleaseBuffer(arg, &varg);
+        PyBuffer_Release(&varg);
         return pos >= 0;
     }
     if (ival < 0 || ival >= 256) {
@@ -964,7 +964,7 @@
 static int
 string_buffer_getbuffer(PyBytesObject *self, Py_buffer *view, int flags)
 {
-	return PyBuffer_FillInfo(view, (void *)self->ob_sval, Py_SIZE(self),
+	return PyBuffer_FillInfo(view, (PyObject*)self, (void *)self->ob_sval, Py_SIZE(self),
 				 1, flags);
 }
 
@@ -1160,7 +1160,7 @@
 
 	if (n == 0) {
 		PyErr_SetString(PyExc_ValueError, "empty separator");
-		PyObject_ReleaseBuffer(subobj, &vsub);
+		PyBuffer_Release(&vsub);
 		return NULL;
 	}
 	else if (n == 1)
@@ -1168,7 +1168,7 @@
 
 	list = PyList_New(PREALLOC_SIZE(maxsplit));
 	if (list == NULL) {
-		PyObject_ReleaseBuffer(subobj, &vsub);
+		PyBuffer_Release(&vsub);
 		return NULL;
 	}
 
@@ -1196,12 +1196,12 @@
 #endif
 	SPLIT_ADD(s, i, len);
 	FIX_PREALLOC_SIZE(list);
-	PyObject_ReleaseBuffer(subobj, &vsub);
+	PyBuffer_Release(&vsub);
 	return list;
 
  onError:
 	Py_DECREF(list);
-	PyObject_ReleaseBuffer(subobj, &vsub);
+	PyBuffer_Release(&vsub);
 	return NULL;
 }
 
@@ -1376,7 +1376,7 @@
 
 	if (n == 0) {
 		PyErr_SetString(PyExc_ValueError, "empty separator");
-		PyObject_ReleaseBuffer(subobj, &vsub);
+		PyBuffer_Release(&vsub);
 		return NULL;
 	}
 	else if (n == 1)
@@ -1384,7 +1384,7 @@
 
 	list = PyList_New(PREALLOC_SIZE(maxsplit));
 	if (list == NULL) {
-		PyObject_ReleaseBuffer(subobj, &vsub);
+		PyBuffer_Release(&vsub);
 		return NULL;
 	}
 
@@ -1406,12 +1406,12 @@
 	FIX_PREALLOC_SIZE(list);
 	if (PyList_Reverse(list) < 0)
 		goto onError;
-	PyObject_ReleaseBuffer(subobj, &vsub);
+	PyBuffer_Release(&vsub);
 	return list;
 
 onError:
 	Py_DECREF(list);
-	PyObject_ReleaseBuffer(subobj, &vsub);
+	PyBuffer_Release(&vsub);
 	return NULL;
 }
 
@@ -1690,7 +1690,7 @@
 		j++;
 	}
 
-	PyObject_ReleaseBuffer(sepobj, &vsep);
+	PyBuffer_Release(&vsep);
 
 	if (i == 0 && j == len && PyBytes_CheckExact(self)) {
 		Py_INCREF(self);
@@ -2945,11 +2945,11 @@
 		if (PyBuffer_ToContiguous(((PyBytesObject *)new)->ob_sval,
 					  &view, view.len, 'C') < 0)
 			goto fail;
-		PyObject_ReleaseBuffer(x, &view);
+		PyBuffer_Release(&view);
 		return new;
 	  fail:
 		Py_XDECREF(new);
-		PyObject_ReleaseBuffer(x, &view);
+		PyBuffer_Release(&view);
 		return NULL;
 	}
 
diff --git a/Objects/memoryobject.c b/Objects/memoryobject.c
index 79d7db1..b36c3a7 100644
--- a/Objects/memoryobject.c
+++ b/Objects/memoryobject.c
@@ -6,19 +6,21 @@
 static int
 memory_getbuf(PyMemoryViewObject *self, Py_buffer *view, int flags)
 {
-        if (view != NULL)
+        if (view != NULL) {
+		if (self->view.obj)
+			Py_INCREF(self->view.obj);
 		*view = self->view;
-	if (self->base == NULL)
+	}
+	if (self->view.obj == NULL)
 		return 0;
-        return self->base->ob_type->tp_as_buffer->bf_getbuffer(self->base, NULL,
+        return self->view.obj->ob_type->tp_as_buffer->bf_getbuffer(self->base, NULL,
                                                                PyBUF_FULL);
 }
 
 static void
 memory_releasebuf(PyMemoryViewObject *self, Py_buffer *view)
 {
-	if (self->base != NULL)
-		PyObject_ReleaseBuffer(self->base, NULL);
+	PyBuffer_Release(&self->view);
 }
 
 PyDoc_STRVAR(memory_doc,
@@ -36,6 +38,8 @@
 	if (mview == NULL) return NULL;
 	mview->base = NULL;
 	mview->view = *info;
+	if (info->obj)
+		Py_INCREF(mview->view.obj);
 	return (PyObject *)mview;
 }
 
@@ -256,7 +260,7 @@
         }
         bytes = PyByteArray_FromStringAndSize(NULL, view->len);
         if (bytes == NULL) {
-                PyObject_ReleaseBuffer(obj, view);
+                PyBuffer_Release(view);
                 return NULL;
         }
         dest = PyByteArray_AS_STRING(bytes);
@@ -271,7 +275,7 @@
         else {
                 if (_indirect_copy_nd(dest, view, fort) < 0) {
                         Py_DECREF(bytes);
-                        PyObject_ReleaseBuffer(obj, view);
+                        PyBuffer_Release(view);
                         return NULL;
                 }
         }
@@ -281,12 +285,12 @@
                 mem->base = PyTuple_Pack(2, obj, bytes);
                 Py_DECREF(bytes);
 		if (mem->base == NULL) {
-			PyObject_ReleaseBuffer(obj, view);
+			PyBuffer_Release(view);
 			return NULL;
 		}
         }
         else {
-                PyObject_ReleaseBuffer(obj, view);
+                PyBuffer_Release(view);
                 /* steal the reference */
                 mem->base = bytes;
         }
@@ -407,7 +411,7 @@
 static void
 memory_dealloc(PyMemoryViewObject *self)
 {
-        if (self->base != NULL) {
+        if (self->view.obj != NULL) {
             if (PyTuple_Check(self->base)) {
                 /* Special case when first element is generic object
                    with buffer interface and the second element is a
@@ -424,11 +428,10 @@
                    be "locked" and was locked and will be unlocked
                    again after this call.
                 */
-                PyObject_ReleaseBuffer(PyTuple_GET_ITEM(self->base,0),
-                                       &(self->view));
+                PyBuffer_Release(&(self->view));
             }
             else {
-                PyObject_ReleaseBuffer(self->base, &(self->view));
+                PyBuffer_Release(&(self->view));
             }
             Py_CLEAR(self->base);
         }
@@ -453,7 +456,7 @@
 
 	res = PyByteArray_FromStringAndSize(NULL, view.len);
         PyBuffer_ToContiguous(PyByteArray_AS_STRING(res), &view, view.len, 'C');
-        PyObject_ReleaseBuffer((PyObject *)self, &view);
+        PyBuffer_Release(&view);
         return res;
 }
 
@@ -466,7 +469,7 @@
 
         if (PyObject_GetBuffer((PyObject *)self, &view, PyBUF_FULL) < 0)
                 return -1;
-        PyObject_ReleaseBuffer((PyObject *)self, &view);
+        PyBuffer_Release(&view);
 	return view.len;
 }
 
diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c
index 897e390..5de265d 100644
--- a/Objects/unicodeobject.c
+++ b/Objects/unicodeobject.c
@@ -1198,7 +1198,7 @@
 
     /* Decode via the codec registry */
     buffer = NULL;
-    if (PyBuffer_FillInfo(&info, (void *)s, size, 1, PyBUF_SIMPLE) < 0)
+    if (PyBuffer_FillInfo(&info, NULL, (void *)s, size, 1, PyBUF_SIMPLE) < 0)
         goto onError;
     buffer = PyMemoryView_FromMemory(&info);
     if (buffer == NULL)