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/_codecsmodule.c b/Modules/_codecsmodule.c
index d4eb0d5..9250e3e 100644
--- a/Modules/_codecsmodule.c
+++ b/Modules/_codecsmodule.c
@@ -232,20 +232,20 @@
 utf_7_decode(PyObject *self,
              PyObject *args)
 {
-    const char *data;
-    Py_ssize_t size;
+	Py_buffer pbuf;
     const char *errors = NULL;
     int final = 0;
     Py_ssize_t consumed;
     PyObject *decoded = NULL;
 
-    if (!PyArg_ParseTuple(args, "t#|zi:utf_7_decode",
-                          &data, &size, &errors, &final))
-        return NULL;
-    consumed = size;
+    if (!PyArg_ParseTuple(args, "s*|zi:utf_7_decode",
+			  &pbuf, &errors, &final))
+	return NULL;
+    consumed = pbuf.len;
 
-    decoded = PyUnicode_DecodeUTF7Stateful(data, size, errors,
-                                           final ? NULL : &consumed);
+    decoded = PyUnicode_DecodeUTF7Stateful(pbuf.buf, pbuf.len, errors,
+					   final ? NULL : &consumed);
+	PyBuffer_Release(&pbuf);
     if (decoded == NULL)
         return NULL;
     return codec_tuple(decoded, consumed);
@@ -255,24 +255,20 @@
 utf_8_decode(PyObject *self,
 	    PyObject *args)
 {
-    const char *data;
-    Py_ssize_t size;
+	Py_buffer pbuf;
     const char *errors = NULL;
     int final = 0;
     Py_ssize_t consumed;
     PyObject *decoded = NULL;
 
-    if (!PyArg_ParseTuple(args, "t#|zi:utf_8_decode",
-			  &data, &size, &errors, &final))
+    if (!PyArg_ParseTuple(args, "s*|zi:utf_8_decode",
+			  &pbuf, &errors, &final))
 	return NULL;
-    if (size < 0) {
-	    PyErr_SetString(PyExc_ValueError, "negative argument");
-	    return 0;
-    }
-    consumed = size;
-	
-    decoded = PyUnicode_DecodeUTF8Stateful(data, size, errors,
+    consumed = pbuf.len;
+
+    decoded = PyUnicode_DecodeUTF8Stateful(pbuf.buf, pbuf.len, errors,
 					   final ? NULL : &consumed);
+	PyBuffer_Release(&pbuf);
     if (decoded == NULL)
 	return NULL;
     return codec_tuple(decoded, consumed);
@@ -282,24 +278,20 @@
 utf_16_decode(PyObject *self,
 	    PyObject *args)
 {
-    const char *data;
-    Py_ssize_t size;
+	Py_buffer pbuf;
     const char *errors = NULL;
     int byteorder = 0;
     int final = 0;
     Py_ssize_t consumed;
     PyObject *decoded;
 
-    if (!PyArg_ParseTuple(args, "t#|zi:utf_16_decode",
-			  &data, &size, &errors, &final))
+    if (!PyArg_ParseTuple(args, "s*|zi:utf_16_decode",
+			  &pbuf, &errors, &final))
 	return NULL;
-    if (size < 0) {
-	    PyErr_SetString(PyExc_ValueError, "negative argument");
-	    return 0;
-    }
-    consumed = size; /* This is overwritten unless final is true. */
-    decoded = PyUnicode_DecodeUTF16Stateful(data, size, errors, &byteorder,
-					    final ? NULL : &consumed);
+    consumed = pbuf.len; /* This is overwritten unless final is true. */
+    decoded = PyUnicode_DecodeUTF16Stateful(pbuf.buf, pbuf.len, errors,
+					&byteorder, final ? NULL : &consumed);
+	PyBuffer_Release(&pbuf);
     if (decoded == NULL)
 	return NULL;
     return codec_tuple(decoded, consumed);
@@ -309,53 +301,45 @@
 utf_16_le_decode(PyObject *self,
 		 PyObject *args)
 {
-    const char *data;
-    Py_ssize_t size;
+	Py_buffer pbuf;
     const char *errors = NULL;
     int byteorder = -1;
     int final = 0;
     Py_ssize_t consumed;
     PyObject *decoded = NULL;
 
-    if (!PyArg_ParseTuple(args, "t#|zi:utf_16_le_decode",
-			  &data, &size, &errors, &final))
+    if (!PyArg_ParseTuple(args, "s*|zi:utf_16_le_decode",
+			  &pbuf, &errors, &final))
 	return NULL;
 
-    if (size < 0) {
-          PyErr_SetString(PyExc_ValueError, "negative argument");
-          return 0;
-    }
-    consumed = size; /* This is overwritten unless final is true. */
-    decoded = PyUnicode_DecodeUTF16Stateful(data, size, errors,
+    consumed = pbuf.len; /* This is overwritten unless final is true. */
+    decoded = PyUnicode_DecodeUTF16Stateful(pbuf.buf, pbuf.len, errors,
 	&byteorder, final ? NULL : &consumed);
+	PyBuffer_Release(&pbuf);
     if (decoded == NULL)
 	return NULL;
     return codec_tuple(decoded, consumed);
-
 }
 
 static PyObject *
 utf_16_be_decode(PyObject *self,
 		 PyObject *args)
 {
-    const char *data;
-    Py_ssize_t size;
+	Py_buffer pbuf;
     const char *errors = NULL;
     int byteorder = 1;
     int final = 0;
     Py_ssize_t consumed;
     PyObject *decoded = NULL;
 
-    if (!PyArg_ParseTuple(args, "t#|zi:utf_16_be_decode",
-			  &data, &size, &errors, &final))
+    if (!PyArg_ParseTuple(args, "s*|zi:utf_16_be_decode",
+			  &pbuf, &errors, &final))
 	return NULL;
-    if (size < 0) {
-          PyErr_SetString(PyExc_ValueError, "negative argument");
-          return 0;
-    }
-    consumed = size; /* This is overwritten unless final is true. */
-    decoded = PyUnicode_DecodeUTF16Stateful(data, size, errors,
+
+    consumed = pbuf.len; /* This is overwritten unless final is true. */
+    decoded = PyUnicode_DecodeUTF16Stateful(pbuf.buf, pbuf.len, errors,
 	&byteorder, final ? NULL : &consumed);
+	PyBuffer_Release(&pbuf);
     if (decoded == NULL)
 	return NULL;
     return codec_tuple(decoded, consumed);
@@ -373,24 +357,20 @@
 utf_16_ex_decode(PyObject *self,
 		 PyObject *args)
 {
-    const char *data;
-    Py_ssize_t size;
+	Py_buffer pbuf;
     const char *errors = NULL;
     int byteorder = 0;
     PyObject *unicode, *tuple;
     int final = 0;
     Py_ssize_t consumed;
 
-    if (!PyArg_ParseTuple(args, "t#|zii:utf_16_ex_decode",
-			  &data, &size, &errors, &byteorder, &final))
+    if (!PyArg_ParseTuple(args, "s*|zii:utf_16_ex_decode",
+			  &pbuf, &errors, &byteorder, &final))
 	return NULL;
-    if (size < 0) {
-	    PyErr_SetString(PyExc_ValueError, "negative argument");
-	    return 0;
-    }
-    consumed = size; /* This is overwritten unless final is true. */
-    unicode = PyUnicode_DecodeUTF16Stateful(data, size, errors, &byteorder,
-					    final ? NULL : &consumed);
+    consumed = pbuf.len; /* This is overwritten unless final is true. */
+    unicode = PyUnicode_DecodeUTF16Stateful(pbuf.buf, pbuf.len, errors,
+					&byteorder, final ? NULL : &consumed);
+	PyBuffer_Release(&pbuf);
     if (unicode == NULL)
 	return NULL;
     tuple = Py_BuildValue("Oni", unicode, consumed, byteorder);
@@ -402,24 +382,20 @@
 utf_32_decode(PyObject *self,
 	    PyObject *args)
 {
-    const char *data;
-    Py_ssize_t size;
+	Py_buffer pbuf;
     const char *errors = NULL;
     int byteorder = 0;
     int final = 0;
     Py_ssize_t consumed;
     PyObject *decoded;
 
-    if (!PyArg_ParseTuple(args, "t#|zi:utf_32_decode",
-			  &data, &size, &errors, &final))
+    if (!PyArg_ParseTuple(args, "s*|zi:utf_32_decode",
+			  &pbuf, &errors, &final))
 	return NULL;
-    if (size < 0) {
-	    PyErr_SetString(PyExc_ValueError, "negative argument");
-	    return 0;
-    }
-    consumed = size; /* This is overwritten unless final is true. */
-    decoded = PyUnicode_DecodeUTF32Stateful(data, size, errors, &byteorder,
-					    final ? NULL : &consumed);
+    consumed = pbuf.len; /* This is overwritten unless final is true. */
+    decoded = PyUnicode_DecodeUTF32Stateful(pbuf.buf, pbuf.len, errors,
+					&byteorder, final ? NULL : &consumed);
+	PyBuffer_Release(&pbuf);
     if (decoded == NULL)
 	return NULL;
     return codec_tuple(decoded, consumed);
@@ -429,53 +405,43 @@
 utf_32_le_decode(PyObject *self,
 		 PyObject *args)
 {
-    const char *data;
-    Py_ssize_t size;
+	Py_buffer pbuf;
     const char *errors = NULL;
     int byteorder = -1;
     int final = 0;
     Py_ssize_t consumed;
-    PyObject *decoded = NULL;
+    PyObject *decoded;
 
-    if (!PyArg_ParseTuple(args, "t#|zi:utf_32_le_decode",
-			  &data, &size, &errors, &final))
+    if (!PyArg_ParseTuple(args, "s*|zi:utf_32_le_decode",
+			  &pbuf, &errors, &final))
 	return NULL;
-
-    if (size < 0) {
-          PyErr_SetString(PyExc_ValueError, "negative argument");
-          return 0;
-    }
-    consumed = size; /* This is overwritten unless final is true. */
-    decoded = PyUnicode_DecodeUTF32Stateful(data, size, errors,
-	&byteorder, final ? NULL : &consumed);
+    consumed = pbuf.len; /* This is overwritten unless final is true. */
+    decoded = PyUnicode_DecodeUTF32Stateful(pbuf.buf, pbuf.len, errors,
+					&byteorder, final ? NULL : &consumed);
+	PyBuffer_Release(&pbuf);
     if (decoded == NULL)
 	return NULL;
     return codec_tuple(decoded, consumed);
-
 }
 
 static PyObject *
 utf_32_be_decode(PyObject *self,
 		 PyObject *args)
 {
-    const char *data;
-    Py_ssize_t size;
+	Py_buffer pbuf;
     const char *errors = NULL;
     int byteorder = 1;
     int final = 0;
     Py_ssize_t consumed;
-    PyObject *decoded = NULL;
+    PyObject *decoded;
 
-    if (!PyArg_ParseTuple(args, "t#|zi:utf_32_be_decode",
-			  &data, &size, &errors, &final))
+    if (!PyArg_ParseTuple(args, "s*|zi:utf_32_be_decode",
+			  &pbuf, &errors, &final))
 	return NULL;
-    if (size < 0) {
-          PyErr_SetString(PyExc_ValueError, "negative argument");
-          return 0;
-    }
-    consumed = size; /* This is overwritten unless final is true. */
-    decoded = PyUnicode_DecodeUTF32Stateful(data, size, errors,
-	&byteorder, final ? NULL : &consumed);
+    consumed = pbuf.len; /* This is overwritten unless final is true. */
+    decoded = PyUnicode_DecodeUTF32Stateful(pbuf.buf, pbuf.len, errors,
+					&byteorder, final ? NULL : &consumed);
+	PyBuffer_Release(&pbuf);
     if (decoded == NULL)
 	return NULL;
     return codec_tuple(decoded, consumed);
@@ -493,24 +459,20 @@
 utf_32_ex_decode(PyObject *self,
 		 PyObject *args)
 {
-    const char *data;
-    Py_ssize_t size;
+	Py_buffer pbuf;
     const char *errors = NULL;
     int byteorder = 0;
     PyObject *unicode, *tuple;
     int final = 0;
     Py_ssize_t consumed;
 
-    if (!PyArg_ParseTuple(args, "t#|zii:utf_32_ex_decode",
-			  &data, &size, &errors, &byteorder, &final))
+    if (!PyArg_ParseTuple(args, "s*|zii:utf_32_ex_decode",
+			  &pbuf, &errors, &byteorder, &final))
 	return NULL;
-    if (size < 0) {
-	    PyErr_SetString(PyExc_ValueError, "negative argument");
-	    return 0;
-    }
-    consumed = size; /* This is overwritten unless final is true. */
-    unicode = PyUnicode_DecodeUTF32Stateful(data, size, errors, &byteorder,
-					    final ? NULL : &consumed);
+    consumed = pbuf.len; /* This is overwritten unless final is true. */
+    unicode = PyUnicode_DecodeUTF32Stateful(pbuf.buf, pbuf.len, errors,
+					&byteorder, final ? NULL : &consumed);
+	PyBuffer_Release(&pbuf);
     if (unicode == NULL)
 	return NULL;
     tuple = Py_BuildValue("Oni", unicode, consumed, byteorder);
@@ -522,83 +484,88 @@
 unicode_escape_decode(PyObject *self,
 		     PyObject *args)
 {
-    const char *data;
-    Py_ssize_t size;
+	Py_buffer pbuf;
     const char *errors = NULL;
+	PyObject *unicode;
 
-    if (!PyArg_ParseTuple(args, "t#|z:unicode_escape_decode",
-			  &data, &size, &errors))
+    if (!PyArg_ParseTuple(args, "s*|z:unicode_escape_decode",
+			  &pbuf, &errors))
 	return NULL;
 
-    return codec_tuple(PyUnicode_DecodeUnicodeEscape(data, size, errors),
-		       size);
+	unicode = PyUnicode_DecodeUnicodeEscape(pbuf.buf, pbuf.len, errors);
+	PyBuffer_Release(&pbuf);
+	return codec_tuple(unicode, pbuf.len);
 }
 
 static PyObject *
 raw_unicode_escape_decode(PyObject *self,
 			PyObject *args)
 {
-    const char *data;
-    Py_ssize_t size;
+	Py_buffer pbuf;
     const char *errors = NULL;
+	PyObject *unicode;
 
-    if (!PyArg_ParseTuple(args, "t#|z:raw_unicode_escape_decode",
-			  &data, &size, &errors))
+    if (!PyArg_ParseTuple(args, "s*|z:raw_unicode_escape_decode",
+			  &pbuf, &errors))
 	return NULL;
 
-    return codec_tuple(PyUnicode_DecodeRawUnicodeEscape(data, size, errors),
-		       size);
+	unicode = PyUnicode_DecodeRawUnicodeEscape(pbuf.buf, pbuf.len, errors);
+	PyBuffer_Release(&pbuf);
+	return codec_tuple(unicode, pbuf.len);
 }
 
 static PyObject *
 latin_1_decode(PyObject *self,
 	       PyObject *args)
 {
-    const char *data;
-    Py_ssize_t size;
+	Py_buffer pbuf;
+	PyObject *unicode;
     const char *errors = NULL;
 
-    if (!PyArg_ParseTuple(args, "t#|z:latin_1_decode",
-			  &data, &size, &errors))
+    if (!PyArg_ParseTuple(args, "s*|z:latin_1_decode",
+			  &pbuf, &errors))
 	return NULL;
 
-    return codec_tuple(PyUnicode_DecodeLatin1(data, size, errors),
-		       size);
+	unicode = PyUnicode_DecodeLatin1(pbuf.buf, pbuf.len, errors);
+	PyBuffer_Release(&pbuf);
+	return codec_tuple(unicode, pbuf.len);
 }
 
 static PyObject *
 ascii_decode(PyObject *self,
 	     PyObject *args)
 {
-    const char *data;
-    Py_ssize_t size;
+	Py_buffer pbuf;
+	PyObject *unicode;
     const char *errors = NULL;
 
-    if (!PyArg_ParseTuple(args, "t#|z:ascii_decode",
-			  &data, &size, &errors))
+    if (!PyArg_ParseTuple(args, "s*|z:ascii_decode",
+			  &pbuf, &errors))
 	return NULL;
 
-    return codec_tuple(PyUnicode_DecodeASCII(data, size, errors),
-		       size);
+	unicode = PyUnicode_DecodeASCII(pbuf.buf, pbuf.len, errors);
+	PyBuffer_Release(&pbuf);
+	return codec_tuple(unicode, pbuf.len);
 }
 
 static PyObject *
 charmap_decode(PyObject *self,
 	       PyObject *args)
 {
-    const char *data;
-    Py_ssize_t size;
+	Py_buffer pbuf;
+	PyObject *unicode;
     const char *errors = NULL;
     PyObject *mapping = NULL;
 
-    if (!PyArg_ParseTuple(args, "t#|zO:charmap_decode",
-			  &data, &size, &errors, &mapping))
+    if (!PyArg_ParseTuple(args, "s*|zO:charmap_decode",
+			  &pbuf, &errors, &mapping))
 	return NULL;
     if (mapping == Py_None)
 	mapping = NULL;
 
-    return codec_tuple(PyUnicode_DecodeCharmap(data, size, mapping, errors),
-		       size);
+	unicode = PyUnicode_DecodeCharmap(pbuf.buf, pbuf.len, mapping, errors);
+	PyBuffer_Release(&pbuf);
+	return codec_tuple(unicode, pbuf.len);
 }
 
 #if defined(MS_WINDOWS) && defined(HAVE_USABLE_WCHAR_T)
@@ -607,21 +574,23 @@
 mbcs_decode(PyObject *self,
 	    PyObject *args)
 {
-    const char *data;
-    Py_ssize_t size, consumed;
+	Py_buffer pbuf;
     const char *errors = NULL;
     int final = 0;
-    PyObject *decoded;
+    Py_ssize_t consumed;
+    PyObject *decoded = NULL;
 
-    if (!PyArg_ParseTuple(args, "t#|zi:mbcs_decode",
-			  &data, &size, &errors, &final))
+    if (!PyArg_ParseTuple(args, "s*|zi:mbcs_decode",
+			  &pbuf, &errors, &final))
 	return NULL;
+    consumed = pbuf.len;
 
-    decoded = PyUnicode_DecodeMBCSStateful(
-	data, size, errors, final ? NULL : &consumed);
-    if (!decoded)
+    decoded = PyUnicode_DecodeMBCSStateful(pbuf.buf, pbuf.len, errors,
+					   final ? NULL : &consumed);
+	PyBuffer_Release(&pbuf);
+    if (decoded == NULL)
 	return NULL;
-    return codec_tuple(decoded, final ? size : consumed);
+    return codec_tuple(decoded, consumed);
 }
 
 #endif /* MS_WINDOWS */
diff --git a/Modules/_fileio.c b/Modules/_fileio.c
index 21608f1..58462dd 100644
--- a/Modules/_fileio.c
+++ b/Modules/_fileio.c
@@ -357,7 +357,7 @@
 static PyObject *
 fileio_readinto(PyFileIOObject *self, PyObject *args)
 {
-	char *ptr;
+	Py_buffer pbuf;
 	Py_ssize_t n;
 
 	if (self->fd < 0)
@@ -365,13 +365,14 @@
 	if (!self->readable)
 		return err_mode("reading");
 
-	if (!PyArg_ParseTuple(args, "w#", &ptr, &n))
+	if (!PyArg_ParseTuple(args, "w*", &pbuf))
 		return NULL;
 
 	Py_BEGIN_ALLOW_THREADS
 	errno = 0;
-	n = read(self->fd, ptr, n);
+	n = read(self->fd, pbuf.buf, pbuf.len);
 	Py_END_ALLOW_THREADS
+	PyBuffer_Release(&pbuf);
 	if (n < 0) {
 		if (errno == EAGAIN)
 			Py_RETURN_NONE;
@@ -489,22 +490,24 @@
 static PyObject *
 fileio_write(PyFileIOObject *self, PyObject *args)
 {
+	Py_buffer pbuf;
 	Py_ssize_t n;
-	char *ptr;
 
 	if (self->fd < 0)
 		return err_closed();
 	if (!self->writable)
 		return err_mode("writing");
 
-	if (!PyArg_ParseTuple(args, "s#", &ptr, &n))
+	if (!PyArg_ParseTuple(args, "s*", &pbuf))
 		return NULL;
 
 	Py_BEGIN_ALLOW_THREADS
 	errno = 0;
-	n = write(self->fd, ptr, n);
+	n = write(self->fd, pbuf.buf, pbuf.len);
 	Py_END_ALLOW_THREADS
 
+	PyBuffer_Release(&pbuf);
+
 	if (n < 0) {
 		if (errno == EAGAIN)
 			Py_RETURN_NONE;
diff --git a/Modules/_multiprocessing/connection.h b/Modules/_multiprocessing/connection.h
index 4b475c6..66a3e8a 100644
--- a/Modules/_multiprocessing/connection.h
+++ b/Modules/_multiprocessing/connection.h
@@ -187,21 +187,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 +235,17 @@
 				PyErr_SetObject(BufferTooShort, result);
 				Py_DECREF(result);
 			}
-			return NULL;
+			goto _error;
 		}
 	}
 
+_cleanup:
+	PyBuffer_Release(&pbuf);
 	return result;
+
+_error:
+	result = NULL;
+	goto _cleanup;
 }
 
 /*
diff --git a/Modules/bz2module.c b/Modules/bz2module.c
index 3929219..b5542bf 100644
--- a/Modules/bz2module.c
+++ b/Modules/bz2module.c
@@ -792,12 +792,15 @@
 BZ2File_write(BZ2FileObject *self, PyObject *args)
 {
 	PyObject *ret = NULL;
+	Py_buffer pbuf;
 	char *buf;
 	int len;
 	int bzerror;
 
-	if (!PyArg_ParseTuple(args, "s#:write", &buf, &len))
+	if (!PyArg_ParseTuple(args, "s*:write", &pbuf))
 		return NULL;
+	buf = pbuf.buf;
+	len = pbuf.len;
 
 	ACQUIRE_LOCK(self);
 	switch (self->mode) {
@@ -831,6 +834,7 @@
 	ret = Py_None;
 
 cleanup:
+	PyBuffer_Release(&pbuf);
 	RELEASE_LOCK(self);
 	return ret;
 }
@@ -1549,6 +1553,7 @@
 static PyObject *
 BZ2Comp_compress(BZ2CompObject *self, PyObject *args)
 {
+	Py_buffer pdata;
 	char *data;
 	int datasize;
 	int bufsize = SMALLCHUNK;
@@ -1557,11 +1562,15 @@
 	bz_stream *bzs = &self->bzs;
 	int bzerror;
 
-	if (!PyArg_ParseTuple(args, "s#:compress", &data, &datasize))
+	if (!PyArg_ParseTuple(args, "s*:compress", &pdata))
 		return NULL;
+	data = pdata.buf;
+	datasize = pdata.len;
 
-	if (datasize == 0)
+	if (datasize == 0) {
+		PyBuffer_Release(&pdata);
 		return PyString_FromString("");
+	}
 
 	ACQUIRE_LOCK(self);
 	if (!self->running) {
@@ -1606,10 +1615,12 @@
 	_PyString_Resize(&ret, (Py_ssize_t)(BZS_TOTAL_OUT(bzs) - totalout));
 
 	RELEASE_LOCK(self);
+	PyBuffer_Release(&pdata);
 	return ret;
 
 error:
 	RELEASE_LOCK(self);
+	PyBuffer_Release(&pdata);
 	Py_XDECREF(ret);
 	return NULL;
 }
@@ -1833,6 +1844,7 @@
 static PyObject *
 BZ2Decomp_decompress(BZ2DecompObject *self, PyObject *args)
 {
+	Py_buffer pdata;
 	char *data;
 	int datasize;
 	int bufsize = SMALLCHUNK;
@@ -1841,8 +1853,10 @@
 	bz_stream *bzs = &self->bzs;
 	int bzerror;
 
-	if (!PyArg_ParseTuple(args, "s#:decompress", &data, &datasize))
+	if (!PyArg_ParseTuple(args, "s*:decompress", &pdata))
 		return NULL;
+	data = pdata.buf;
+	datasize = pdata.len;
 
 	ACQUIRE_LOCK(self);
 	if (!self->running) {
@@ -1899,10 +1913,12 @@
 		_PyString_Resize(&ret, (Py_ssize_t)(BZS_TOTAL_OUT(bzs) - totalout));
 
 	RELEASE_LOCK(self);
+	PyBuffer_Release(&pdata);
 	return ret;
 
 error:
 	RELEASE_LOCK(self);
+	PyBuffer_Release(&pdata);
 	Py_XDECREF(ret);
 	return NULL;
 }
@@ -2041,6 +2057,7 @@
 bz2_compress(PyObject *self, PyObject *args, PyObject *kwargs)
 {
 	int compresslevel=9;
+	Py_buffer pdata;
 	char *data;
 	int datasize;
 	int bufsize;
@@ -2050,14 +2067,17 @@
 	int bzerror;
 	static char *kwlist[] = {"data", "compresslevel", 0};
 
-	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s#|i",
-					 kwlist, &data, &datasize,
+	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s*|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;
 	}
 
@@ -2066,8 +2086,10 @@
 	bufsize = datasize + (datasize/100+1) + 600;
 
 	ret = PyString_FromStringAndSize(NULL, bufsize);
-	if (!ret)
+	if (!ret) {
+		PyBuffer_Release(&pdata);
 		return NULL;
+	}
 
 	memset(bzs, 0, sizeof(bz_stream));
 
@@ -2079,6 +2101,7 @@
 	bzerror = BZ2_bzCompressInit(bzs, compresslevel, 0, 0);
 	if (bzerror != BZ_OK) {
 		Util_CatchBZ2Error(bzerror);
+		PyBuffer_Release(&pdata);
 		Py_DECREF(ret);
 		return NULL;
 	}
@@ -2092,6 +2115,7 @@
 		} else if (bzerror != BZ_FINISH_OK) {
 			BZ2_bzCompressEnd(bzs);
 			Util_CatchBZ2Error(bzerror);
+			PyBuffer_Release(&pdata);
 			Py_DECREF(ret);
 			return NULL;
 		}
@@ -2099,6 +2123,7 @@
 			bufsize = Util_NewBufferSize(bufsize);
 			if (_PyString_Resize(&ret, bufsize) < 0) {
 				BZ2_bzCompressEnd(bzs);
+				PyBuffer_Release(&pdata);
 				Py_DECREF(ret);
 				return NULL;
 			}
@@ -2111,6 +2136,7 @@
 		_PyString_Resize(&ret, (Py_ssize_t)BZS_TOTAL_OUT(bzs));
 	BZ2_bzCompressEnd(bzs);
 
+	PyBuffer_Release(&pdata);
 	return ret;
 }
 
@@ -2124,6 +2150,7 @@
 static PyObject *
 bz2_decompress(PyObject *self, PyObject *args)
 {
+	Py_buffer pdata;
 	char *data;
 	int datasize;
 	int bufsize = SMALLCHUNK;
@@ -2132,15 +2159,21 @@
 	bz_stream *bzs = &_bzs;
 	int bzerror;
 
-	if (!PyArg_ParseTuple(args, "s#:decompress", &data, &datasize))
+	if (!PyArg_ParseTuple(args, "s*:decompress", &pdata))
 		return NULL;
+	data = pdata.buf;
+	datasize = pdata.len;
 
-	if (datasize == 0)
+	if (datasize == 0) {
+		PyBuffer_Release(&pdata);
 		return PyString_FromString("");
+	}
 
 	ret = PyString_FromStringAndSize(NULL, bufsize);
-	if (!ret)
+	if (!ret) {
+		PyBuffer_Release(&pdata);
 		return NULL;
+	}
 
 	memset(bzs, 0, sizeof(bz_stream));
 
@@ -2153,6 +2186,7 @@
 	if (bzerror != BZ_OK) {
 		Util_CatchBZ2Error(bzerror);
 		Py_DECREF(ret);
+		PyBuffer_Release(&pdata);
 		return NULL;
 	}
 
@@ -2165,6 +2199,7 @@
 		} else if (bzerror != BZ_OK) {
 			BZ2_bzDecompressEnd(bzs);
 			Util_CatchBZ2Error(bzerror);
+			PyBuffer_Release(&pdata);
 			Py_DECREF(ret);
 			return NULL;
 		}
@@ -2172,6 +2207,7 @@
 			BZ2_bzDecompressEnd(bzs);
 			PyErr_SetString(PyExc_ValueError,
 					"couldn't find end of stream");
+			PyBuffer_Release(&pdata);
 			Py_DECREF(ret);
 			return NULL;
 		}
@@ -2179,6 +2215,7 @@
 			bufsize = Util_NewBufferSize(bufsize);
 			if (_PyString_Resize(&ret, bufsize) < 0) {
 				BZ2_bzDecompressEnd(bzs);
+				PyBuffer_Release(&pdata);
 				Py_DECREF(ret);
 				return NULL;
 			}
@@ -2190,6 +2227,7 @@
 	if (bzs->avail_out != 0)
 		_PyString_Resize(&ret, (Py_ssize_t)BZS_TOTAL_OUT(bzs));
 	BZ2_bzDecompressEnd(bzs);
+	PyBuffer_Release(&pdata);
 
 	return ret;
 }
diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c
index f18e154..8104ccd 100644
--- a/Modules/posixmodule.c
+++ b/Modules/posixmodule.c
@@ -6334,15 +6334,16 @@
 static PyObject *
 posix_write(PyObject *self, PyObject *args)
 {
+	Py_buffer pbuf;
 	int fd;
 	Py_ssize_t size;
-	char *buffer;
 
-	if (!PyArg_ParseTuple(args, "is#:write", &fd, &buffer, &size))
+	if (!PyArg_ParseTuple(args, "is*:write", &fd, &pbuf))
 		return NULL;
 	Py_BEGIN_ALLOW_THREADS
-	size = write(fd, buffer, (size_t)size);
+	size = write(fd, pbuf.buf, (size_t)pbuf.len);
 	Py_END_ALLOW_THREADS
+		PyBuffer_Release(&pbuf);
 	if (size < 0)
 		return posix_error();
 	return PyInt_FromSsize_t(size);
diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c
index e4c8ac8..deff28a 100644
--- a/Modules/socketmodule.c
+++ b/Modules/socketmodule.c
@@ -2647,12 +2647,17 @@
 {
 	char *buf;
 	int len, n = -1, flags = 0, timeout;
+	Py_buffer pbuf;
 
-	if (!PyArg_ParseTuple(args, "s#|i:send", &buf, &len, &flags))
+	if (!PyArg_ParseTuple(args, "s*|i:send", &pbuf, &flags))
 		return NULL;
 
-	if (!IS_SELECTABLE(s))
+	if (!IS_SELECTABLE(s)) {
+		PyBuffer_Release(&pbuf);
 		return select_error();
+	}
+	buf = pbuf.buf;
+	len = pbuf.len;
 
 	Py_BEGIN_ALLOW_THREADS
 	timeout = internal_select(s, 1);
@@ -2664,6 +2669,8 @@
 #endif
 	Py_END_ALLOW_THREADS
 
+	PyBuffer_Release(&pbuf);
+
 	if (timeout == 1) {
 		PyErr_SetString(socket_timeout, "timed out");
 		return NULL;
@@ -2688,12 +2695,17 @@
 {
 	char *buf;
 	int len, n = -1, flags = 0, timeout;
+	Py_buffer pbuf;
 
-	if (!PyArg_ParseTuple(args, "s#|i:sendall", &buf, &len, &flags))
+	if (!PyArg_ParseTuple(args, "s*|i:sendall", &pbuf, &flags))
 		return NULL;
+	buf = pbuf.buf;
+	len = pbuf.len;
 
-	if (!IS_SELECTABLE(s))
+	if (!IS_SELECTABLE(s)) {
+		PyBuffer_Release(&pbuf);
 		return select_error();
+	}
 
 	Py_BEGIN_ALLOW_THREADS
 	do {
@@ -2712,6 +2724,7 @@
 		len -= n;
 	} while (len > 0);
 	Py_END_ALLOW_THREADS
+	PyBuffer_Release(&pbuf);
 
 	if (timeout == 1) {
 		PyErr_SetString(socket_timeout, "timed out");
@@ -2738,24 +2751,32 @@
 static PyObject *
 sock_sendto(PySocketSockObject *s, PyObject *args)
 {
+	Py_buffer pbuf;
 	PyObject *addro;
 	char *buf;
+	Py_ssize_t len;
 	sock_addr_t addrbuf;
-	int addrlen, len, n = -1, flags, timeout;
+	int addrlen, n = -1, flags, timeout;
 
 	flags = 0;
-	if (!PyArg_ParseTuple(args, "s#O:sendto", &buf, &len, &addro)) {
+	if (!PyArg_ParseTuple(args, "s*O:sendto", &pbuf, &addro)) {
 		PyErr_Clear();
-		if (!PyArg_ParseTuple(args, "s#iO:sendto",
-				      &buf, &len, &flags, &addro))
+		if (!PyArg_ParseTuple(args, "s*iO:sendto",
+				      &pbuf, &flags, &addro))
 			return NULL;
 	}
+	buf = pbuf.buf;
+	len = pbuf.len;
 
-	if (!IS_SELECTABLE(s))
+	if (!IS_SELECTABLE(s)) {
+		PyBuffer_Release(&pbuf);
 		return select_error();
+	}
 
-	if (!getsockaddrarg(s, addro, SAS2SA(&addrbuf), &addrlen))
+	if (!getsockaddrarg(s, addro, SAS2SA(&addrbuf), &addrlen)) {
+		PyBuffer_Release(&pbuf);
 		return NULL;
+	}
 
 	Py_BEGIN_ALLOW_THREADS
 	timeout = internal_select(s, 1);
@@ -2763,6 +2784,7 @@
 		n = sendto(s->sock_fd, buf, len, flags, SAS2SA(&addrbuf), addrlen);
 	Py_END_ALLOW_THREADS
 
+	PyBuffer_Release(&pbuf);
 	if (timeout == 1) {
 		PyErr_SetString(socket_timeout, "timed out");
 		return NULL;