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/bz2module.c b/Modules/bz2module.c
index c681991..4bf31ee 100644
--- a/Modules/bz2module.c
+++ b/Modules/bz2module.c
@@ -691,12 +691,15 @@
 BZ2File_write(BZ2FileObject *self, PyObject *args)
 {
 	PyObject *ret = NULL;
+	Py_buffer pbuf;
 	char *buf;
 	int len;
 	int bzerror;
 
-	if (!PyArg_ParseTuple(args, "y#:write", &buf, &len))
+	if (!PyArg_ParseTuple(args, "y*:write", &pbuf))
 		return NULL;
+	buf = pbuf.buf;
+	len = pbuf.len;
 
 	ACQUIRE_LOCK(self);
 	switch (self->mode) {
@@ -728,6 +731,7 @@
 	ret = Py_None;
 
 cleanup:
+	PyBuffer_Release(&pbuf);
 	RELEASE_LOCK(self);
 	return ret;
 }
@@ -1353,6 +1357,7 @@
 static PyObject *
 BZ2Comp_compress(BZ2CompObject *self, PyObject *args)
 {
+	Py_buffer pdata;
 	char *data;
 	int datasize;
 	int bufsize = SMALLCHUNK;
@@ -1361,11 +1366,15 @@
 	bz_stream *bzs = &self->bzs;
 	int bzerror;
 
-	if (!PyArg_ParseTuple(args, "y#:compress", &data, &datasize))
+	if (!PyArg_ParseTuple(args, "y*:compress", &pdata))
 		return NULL;
+	data = pdata.buf;
+	datasize = pdata.len;
 
-	if (datasize == 0)
+	if (datasize == 0) {
+		PyBuffer_Release(&pdata);
 		return PyBytes_FromStringAndSize("", 0);
+	}
 
 	ACQUIRE_LOCK(self);
 	if (!self->running) {
@@ -1412,10 +1421,12 @@
 		goto error;
 
 	RELEASE_LOCK(self);
+	PyBuffer_Release(&pdata);
 	return ret;
 
 error:
 	RELEASE_LOCK(self);
+	PyBuffer_Release(&pdata);
 	Py_XDECREF(ret);
 	return NULL;
 }
@@ -1642,6 +1653,7 @@
 static PyObject *
 BZ2Decomp_decompress(BZ2DecompObject *self, PyObject *args)
 {
+	Py_buffer pdata;
 	char *data;
 	int datasize;
 	int bufsize = SMALLCHUNK;
@@ -1650,8 +1662,10 @@
 	bz_stream *bzs = &self->bzs;
 	int bzerror;
 
-	if (!PyArg_ParseTuple(args, "y#:decompress", &data, &datasize))
+	if (!PyArg_ParseTuple(args, "y*:decompress", &pdata))
 		return NULL;
+	data = pdata.buf;
+	datasize = pdata.len;
 
 	ACQUIRE_LOCK(self);
 	if (!self->running) {
@@ -1711,10 +1725,12 @@
 	}
 
 	RELEASE_LOCK(self);
+	PyBuffer_Release(&pdata);
 	return ret;
 
 error:
 	RELEASE_LOCK(self);
+	PyBuffer_Release(&pdata);
 	Py_XDECREF(ret);
 	return NULL;
 }
@@ -1853,6 +1869,7 @@
 bz2_compress(PyObject *self, PyObject *args, PyObject *kwargs)
 {
 	int compresslevel=9;
+	Py_buffer pdata;
 	char *data;
 	int datasize;
 	int bufsize;
@@ -1862,14 +1879,17 @@
 	int bzerror;
 	static char *kwlist[] = {"data", "compresslevel", 0};
 
-	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "y#|i",
-					 kwlist, &data, &datasize,
+	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "y*|i",
+					 kwlist, &pdata,
 					 &compresslevel))
 		return NULL;
+	data = pdata.buf;
+	datasize = pdata.len;
 
 	if (compresslevel < 1 || compresslevel > 9) {
 		PyErr_SetString(PyExc_ValueError,
 				"compresslevel must be between 1 and 9");
+		PyBuffer_Release(&pdata);
 		return NULL;
 	}
 
@@ -1878,8 +1898,10 @@
 	bufsize = datasize + (datasize/100+1) + 600;
 
 	ret = PyBytes_FromStringAndSize(NULL, bufsize);
-	if (!ret)
+	if (!ret) {
+		PyBuffer_Release(&pdata);
 		return NULL;
+	}
 
 	memset(bzs, 0, sizeof(bz_stream));
 
@@ -1891,6 +1913,7 @@
 	bzerror = BZ2_bzCompressInit(bzs, compresslevel, 0, 0);
 	if (bzerror != BZ_OK) {
 		Util_CatchBZ2Error(bzerror);
+		PyBuffer_Release(&pdata);
 		Py_DECREF(ret);
 		return NULL;
 	}
@@ -1904,6 +1927,7 @@
 		} else if (bzerror != BZ_FINISH_OK) {
 			BZ2_bzCompressEnd(bzs);
 			Util_CatchBZ2Error(bzerror);
+			PyBuffer_Release(&pdata);
 			Py_DECREF(ret);
 			return NULL;
 		}
@@ -1911,6 +1935,7 @@
 			bufsize = Util_NewBufferSize(bufsize);
 			if (_PyBytes_Resize(&ret, bufsize) < 0) {
 				BZ2_bzCompressEnd(bzs);
+				PyBuffer_Release(&pdata);
 				return NULL;
 			}
 			bzs->next_out = BUF(ret) + BZS_TOTAL_OUT(bzs);
@@ -1925,6 +1950,7 @@
 	}
 	BZ2_bzCompressEnd(bzs);
 
+	PyBuffer_Release(&pdata);
 	return ret;
 }
 
@@ -1938,6 +1964,7 @@
 static PyObject *
 bz2_decompress(PyObject *self, PyObject *args)
 {
+	Py_buffer pdata;
 	char *data;
 	int datasize;
 	int bufsize = SMALLCHUNK;
@@ -1946,15 +1973,21 @@
 	bz_stream *bzs = &_bzs;
 	int bzerror;
 
-	if (!PyArg_ParseTuple(args, "y#:decompress", &data, &datasize))
+	if (!PyArg_ParseTuple(args, "y*:decompress", &pdata))
 		return NULL;
+	data = pdata.buf;
+	datasize = pdata.len;
 
-	if (datasize == 0)
+	if (datasize == 0) {
+		PyBuffer_Release(&pdata);
 		return PyBytes_FromStringAndSize("", 0);
+	}
 
 	ret = PyBytes_FromStringAndSize(NULL, bufsize);
-	if (!ret)
+	if (!ret) {
+		PyBuffer_Release(&pdata);
 		return NULL;
+	}
 
 	memset(bzs, 0, sizeof(bz_stream));
 
@@ -1967,6 +2000,7 @@
 	if (bzerror != BZ_OK) {
 		Util_CatchBZ2Error(bzerror);
 		Py_DECREF(ret);
+		PyBuffer_Release(&pdata);
 		return NULL;
 	}
 
@@ -1979,6 +2013,7 @@
 		} else if (bzerror != BZ_OK) {
 			BZ2_bzDecompressEnd(bzs);
 			Util_CatchBZ2Error(bzerror);
+			PyBuffer_Release(&pdata);
 			Py_DECREF(ret);
 			return NULL;
 		}
@@ -1986,6 +2021,7 @@
 			BZ2_bzDecompressEnd(bzs);
 			PyErr_SetString(PyExc_ValueError,
 					"couldn't find end of stream");
+			PyBuffer_Release(&pdata);
 			Py_DECREF(ret);
 			return NULL;
 		}
@@ -1993,6 +2029,7 @@
 			bufsize = Util_NewBufferSize(bufsize);
 			if (_PyBytes_Resize(&ret, bufsize) < 0) {
 				BZ2_bzDecompressEnd(bzs);
+				PyBuffer_Release(&pdata);
 				return NULL;
 			}
 			bzs->next_out = BUF(ret) + BZS_TOTAL_OUT(bzs);
@@ -2006,6 +2043,7 @@
 		}
 	}
 	BZ2_bzDecompressEnd(bzs);
+	PyBuffer_Release(&pdata);
 
 	return ret;
 }