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/Modules/_multiprocessing/connection.h b/Modules/_multiprocessing/connection.h
index d651a97..e422d69 100644
--- a/Modules/_multiprocessing/connection.h
+++ b/Modules/_multiprocessing/connection.h
@@ -96,21 +96,26 @@
 static PyObject *
 connection_sendbytes(ConnectionObject *self, PyObject *args)
 {
+	Py_buffer pbuffer;
 	char *buffer;
 	Py_ssize_t length, offset=0, size=PY_SSIZE_T_MIN;
 	int res;
 
-	if (!PyArg_ParseTuple(args, F_RBUFFER "#|" F_PY_SSIZE_T F_PY_SSIZE_T,
-			      &buffer, &length, &offset, &size))
+	if (!PyArg_ParseTuple(args, F_RBUFFER "*|" F_PY_SSIZE_T F_PY_SSIZE_T,
+			      &pbuffer, &offset, &size))
 		return NULL;
+	buffer = pbuffer.buf;
+	length = pbuffer.len;
 
-	CHECK_WRITABLE(self);
+	CHECK_WRITABLE(self); /* XXX release buffer in case of failure */
 
 	if (offset < 0) {
+		PyBuffer_Release(&pbuffer);
 		PyErr_SetString(PyExc_ValueError, "offset is negative");
 		return NULL;
 	}
 	if (length < offset) {
+		PyBuffer_Release(&pbuffer);
 		PyErr_SetString(PyExc_ValueError, "buffer length < offset");
 		return NULL;
 	}
@@ -119,10 +124,12 @@
 		size = length - offset;
 	} else {
 		if (size < 0) {
+			PyBuffer_Release(&pbuffer);
 			PyErr_SetString(PyExc_ValueError, "size is negative");
 			return NULL;		
 		}
 		if (offset + size > length) {
+			PyBuffer_Release(&pbuffer);
 			PyErr_SetString(PyExc_ValueError, 
 					"buffer length < offset + size");
 			return NULL;
@@ -131,6 +138,7 @@
 
 	res = conn_send_string(self, buffer + offset, size);
 
+	PyBuffer_Release(&pbuffer);
 	if (res < 0)
 		return mp_SetError(PyExc_IOError, res);
 
@@ -187,21 +195,25 @@
 	char *freeme = NULL, *buffer = NULL;
 	Py_ssize_t res, length, offset = 0;
 	PyObject *result = NULL;
-
-	if (!PyArg_ParseTuple(args, "w#|" F_PY_SSIZE_T, 
-			      &buffer, &length, &offset))
-		return NULL;
+	Py_buffer pbuf;
 
 	CHECK_READABLE(self);
+	
+	if (!PyArg_ParseTuple(args, "w*|" F_PY_SSIZE_T, 
+			      &pbuf, &offset))
+		return NULL;
+
+	buffer = pbuf.buf;
+	length = pbuf.len;
 
 	if (offset < 0) {
 		PyErr_SetString(PyExc_ValueError, "negative offset");
-		return NULL;
+		goto _error;
 	}   
 
 	if (offset > length) {
 		PyErr_SetString(PyExc_ValueError, "offset too large");
-		return NULL;
+		goto _error;
 	}
 
 	res = conn_recv_string(self, buffer+offset, length-offset, 
@@ -231,11 +243,17 @@
 				PyErr_SetObject(BufferTooShort, result);
 				Py_DECREF(result);
 			}
-			return NULL;
+			goto _error;
 		}
 	}
 
+_cleanup:
+	PyBuffer_Release(&pbuf);
 	return result;
+
+_error:
+	result = NULL;
+	goto _cleanup;
 }
 
 /*