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/_bsddb.c b/Modules/_bsddb.c
index 648fb0d..7c0eae3 100644
--- a/Modules/_bsddb.c
+++ b/Modules/_bsddb.c
@@ -288,7 +288,7 @@
 static void free_buf_view(PyObject *obj, Py_buffer *view)
 {
     if (view) {
-        PyObject_ReleaseBuffer(obj, view);
+        PyBuffer_Release(view);
         PyMem_Free(view);
     }
 }
@@ -319,7 +319,7 @@
     if (view->ndim > 1) {
         PyErr_SetString(PyExc_BufferError,
                         "buffers must be single dimension");
-        PyObject_ReleaseBuffer(obj, view);
+        PyBuffer_Release(view);
         PyMem_Free(view);
         return NULL;
     }
diff --git a/Modules/_codecsmodule.c b/Modules/_codecsmodule.c
index 96dfd56..5026c05 100644
--- a/Modules/_codecsmodule.c
+++ b/Modules/_codecsmodule.c
@@ -252,20 +252,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);
@@ -275,24 +275,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);
@@ -302,24 +298,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);
@@ -329,53 +321,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);
@@ -393,24 +377,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);
@@ -422,24 +402,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);
@@ -449,53 +425,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);
@@ -513,24 +479,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);
@@ -542,83 +504,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)
@@ -627,21 +594,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 */
@@ -652,15 +621,21 @@
 readbuffer_encode(PyObject *self,
 		  PyObject *args)
 {
+    Py_buffer pdata;
     const char *data;
     Py_ssize_t size;
     const char *errors = NULL;
+    PyObject *result;
 
-    if (!PyArg_ParseTuple(args, "s#|z:readbuffer_encode",
-			  &data, &size, &errors))
+    if (!PyArg_ParseTuple(args, "s*|z:readbuffer_encode",
+			  &pdata, &errors))
 	return NULL;
+    data = pdata.buf;
+    size = pdata.len;
 
-    return codec_tuple(PyBytes_FromStringAndSize(data, size), size);
+    result = PyBytes_FromStringAndSize(data, size);
+    PyBuffer_Release(&pdata);
+    return codec_tuple(result, size);
 }
 
 static PyObject *
diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c
index 02a08a4..7ef3ea1 100644
--- a/Modules/_ctypes/_ctypes.c
+++ b/Modules/_ctypes/_ctypes.c
@@ -1050,10 +1050,10 @@
 
 	memcpy(self->b_ptr, ptr, size);
 
-	PyObject_ReleaseBuffer(value, &view);
+	PyBuffer_Release(&view);
 	return 0;
  fail:
-	PyObject_ReleaseBuffer(value, &view);
+	PyBuffer_Release(&view);
         return -1;
 }
 
@@ -2462,6 +2462,8 @@
 	if (view == NULL) return 0;
 
 	view->buf = self->b_ptr;
+	view->obj = _self;
+	Py_INCREF(_self);
 	view->len = self->b_size;
 	view->readonly = 0;
 	/* use default format character if not set */
diff --git a/Modules/_fileio.c b/Modules/_fileio.c
index f520f0c..f0c8fed 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/_hashopenssl.c b/Modules/_hashopenssl.c
index bd04411..c0f9a2c 100644
--- a/Modules/_hashopenssl.c
+++ b/Modules/_hashopenssl.c
@@ -164,7 +164,7 @@
                 if ((viewp)->ndim > 1) { \
                     PyErr_SetString(PyExc_BufferError, \
                                     "Buffer must be single dimension"); \
-                    PyObject_ReleaseBuffer((obj), (viewp)); \
+                    PyBuffer_Release((viewp)); \
                     return NULL; \
                 } \
             } while(0);
@@ -186,7 +186,7 @@
     EVP_DigestUpdate(&self->ctx, (unsigned char*)view.buf,
                      Py_SAFE_DOWNCAST(view.len, Py_ssize_t, unsigned int));
 
-    PyObject_ReleaseBuffer(obj, &view);
+    PyBuffer_Release(&view);
 
     Py_INCREF(Py_None);
     return Py_None;
@@ -267,7 +267,7 @@
     if (!PyArg_Parse(name_obj, "s", &nameStr)) {
         PyErr_SetString(PyExc_TypeError, "name must be a string");
         if (data_obj)
-            PyObject_ReleaseBuffer(data_obj, &view);
+            PyBuffer_Release(&view);
         return -1;
     }
 
@@ -275,7 +275,7 @@
     if (!digest) {
         PyErr_SetString(PyExc_ValueError, "unknown hash function");
         if (data_obj)
-            PyObject_ReleaseBuffer(data_obj, &view);
+            PyBuffer_Release(&view);
         return -1;
     }
     EVP_DigestInit(&self->ctx, digest);
@@ -286,7 +286,7 @@
     if (data_obj) {
         EVP_DigestUpdate(&self->ctx, (unsigned char*)view.buf,
                          Py_SAFE_DOWNCAST(view.len, Py_ssize_t, unsigned int));
-        PyObject_ReleaseBuffer(data_obj, &view);
+        PyBuffer_Release(&view);
     }
 
     return 0;
@@ -421,7 +421,7 @@
                         Py_SAFE_DOWNCAST(view.len, Py_ssize_t, unsigned int));
 
     if (data_obj)
-        PyObject_ReleaseBuffer(data_obj, &view);
+        PyBuffer_Release(&view);
     return ret_obj;
 }
 
@@ -455,7 +455,7 @@
                     Py_SAFE_DOWNCAST(view.len, Py_ssize_t, unsigned int)); \
      \
         if (data_obj) \
-            PyObject_ReleaseBuffer(data_obj, &view); \
+            PyBuffer_Release(&view); \
         return ret_obj; \
     }
 
diff --git a/Modules/_json.c b/Modules/_json.c
index 1cf1e63..a724f89 100644
--- a/Modules/_json.c
+++ b/Modules/_json.c
@@ -261,7 +261,7 @@
         /* Pick up this chunk if it's not zero length */
         if (next != end) {
             PyObject *strchunk;
-            if (PyBuffer_FillInfo(&info, &buf[end], next - end, 1, 0) < 0) {
+            if (PyBuffer_FillInfo(&info, NULL, &buf[end], next - end, 1, 0) < 0) {
                 goto bail;
             }
             strchunk = PyMemoryView_FromMemory(&info);
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;
 }
 
 /*
diff --git a/Modules/_sre.c b/Modules/_sre.c
index 4511c1b..64fc513 100644
--- a/Modules/_sre.c
+++ b/Modules/_sre.c
@@ -1704,7 +1704,7 @@
     /* Release the buffer immediately --- possibly dangerous
        but doing something else would require some re-factoring
     */
-    PyObject_ReleaseBuffer(string, &view);
+    PyBuffer_Release(&view);
 
     if (bytes < 0) {
         PyErr_SetString(PyExc_TypeError, "buffer has negative size");
diff --git a/Modules/_struct.c b/Modules/_struct.c
index 43be9ed..4a257c0 100644
--- a/Modules/_struct.c
+++ b/Modules/_struct.c
@@ -1567,11 +1567,11 @@
 		PyErr_Format(StructError,
 			     "unpack requires a bytes argument of length %zd",
 			     soself->s_size);
-                PyObject_ReleaseBuffer(input, &vbuf);
+                PyBuffer_Release(&vbuf);
 		return NULL;
 	}
 	result = s_unpack_internal(soself, vbuf.buf);
-	PyObject_ReleaseBuffer(input, &vbuf);
+	PyBuffer_Release(&vbuf);
 	return result;
 }
 
@@ -1609,11 +1609,11 @@
 		PyErr_Format(StructError,
 			"unpack_from requires a buffer of at least %zd bytes",
 			soself->s_size);
-                PyObject_ReleaseBuffer(input, &vbuf);
+                PyBuffer_Release(&vbuf);
 		return NULL;
 	}
 	result = s_unpack_internal(soself, (char*)vbuf.buf + offset);
-	PyObject_ReleaseBuffer(input, &vbuf);
+	PyBuffer_Release(&vbuf);
 	return result;
 }
 
diff --git a/Modules/arraymodule.c b/Modules/arraymodule.c
index b5f819e..16a7a7e 100644
--- a/Modules/arraymodule.c
+++ b/Modules/arraymodule.c
@@ -1820,6 +1820,8 @@
         if (view==NULL) goto finish;
 
         view->buf = (void *)self->ob_item;
+	view->obj = (PyObject*)self;
+	Py_INCREF(self);
         if (view->buf == NULL)
                 view->buf = (void *)emptybuf;
         view->len = (Py_SIZE(self)) * self->ob_descr->itemsize;
diff --git a/Modules/audioop.c b/Modules/audioop.c
index c54e512..b2fdb9a 100644
--- a/Modules/audioop.c
+++ b/Modules/audioop.c
@@ -783,20 +783,24 @@
 static PyObject *
 audioop_tomono(PyObject *self, PyObject *args)
 {
+	Py_buffer pcp;
         signed char *cp, *ncp;
         int len, size, val1 = 0, val2 = 0;
         double fac1, fac2, fval, maxval;
         PyObject *rv;
         int i;
 
-        if ( !PyArg_ParseTuple(args, "s#idd:tomono",
-	                       &cp, &len, &size, &fac1, &fac2 ) )
+        if ( !PyArg_ParseTuple(args, "s*idd:tomono",
+	                       &pcp, &size, &fac1, &fac2 ) )
                 return 0;
+	cp = pcp.buf;
+	len = pcp.len;
     
         if ( size == 1 ) maxval = (double) 0x7f;
         else if ( size == 2 ) maxval = (double) 0x7fff;
         else if ( size == 4 ) maxval = (double) 0x7fffffff;
         else {
+		PyBuffer_Release(&pcp);
                 PyErr_SetString(AudioopError, "Size should be 1, 2 or 4");
                 return 0;
         }
@@ -822,6 +826,7 @@
                 else if ( size == 2 ) *SHORTP(ncp, i/2) = (short)val1;
                 else if ( size == 4 ) *LONGP(ncp, i/2)= (Py_Int32)val1;
         }
+	PyBuffer_Release(&pcp);
         return rv;
 }
 
diff --git a/Modules/binascii.c b/Modules/binascii.c
index ea34bcd..3c27fd6 100644
--- a/Modules/binascii.c
+++ b/Modules/binascii.c
@@ -188,6 +188,7 @@
 static PyObject *
 binascii_a2b_uu(PyObject *self, PyObject *args)
 {
+	Py_buffer pascii;
 	unsigned char *ascii_data, *bin_data;
 	int leftbits = 0;
 	unsigned char this_ch;
@@ -195,8 +196,10 @@
 	PyObject *rv;
 	Py_ssize_t ascii_len, bin_len;
 
-	if ( !PyArg_ParseTuple(args, "t#:a2b_uu", &ascii_data, &ascii_len) )
+	if ( !PyArg_ParseTuple(args, "y*:a2b_uu", &pascii) )
 		return NULL;
+	ascii_data = pascii.buf;
+	ascii_len = pascii.len;
 
 	assert(ascii_len >= 0);
 
@@ -205,8 +208,10 @@
 	ascii_len--;
 
 	/* Allocate the buffer */
-	if ( (rv=PyBytes_FromStringAndSize(NULL, bin_len)) == NULL )
+	if ( (rv=PyBytes_FromStringAndSize(NULL, bin_len)) == NULL ) {
+		PyBuffer_Release(&pascii);
 		return NULL;
+	}
 	bin_data = (unsigned char *)PyBytes_AS_STRING(rv);
 
 	for( ; bin_len > 0 ; ascii_len--, ascii_data++ ) {
@@ -258,6 +263,7 @@
 			return NULL;
 		}
 	}
+	PyBuffer_Release(&pascii);
 	return rv;
 }
 
@@ -266,6 +272,7 @@
 static PyObject *
 binascii_b2a_uu(PyObject *self, PyObject *args)
 {
+	Py_buffer pbin;
 	unsigned char *ascii_data, *bin_data;
 	int leftbits = 0;
 	unsigned char this_ch;
@@ -273,17 +280,22 @@
 	PyObject *rv;
 	Py_ssize_t bin_len;
 
-	if ( !PyArg_ParseTuple(args, "s#:b2a_uu", &bin_data, &bin_len) )
+	if ( !PyArg_ParseTuple(args, "s*:b2a_uu", &pbin) )
 		return NULL;
+	bin_data = pbin.buf;
+	bin_len = pbin.len;
 	if ( bin_len > 45 ) {
 		/* The 45 is a limit that appears in all uuencode's */
 		PyErr_SetString(Error, "At most 45 bytes at once");
+		PyBuffer_Release(&pbin);
 		return NULL;
 	}
 
 	/* We're lazy and allocate to much (fixed up later) */
-	if ( (rv=PyBytes_FromStringAndSize(NULL, bin_len*2+2)) == NULL )
+	if ( (rv=PyBytes_FromStringAndSize(NULL, bin_len*2+2)) == NULL ) {
+		PyBuffer_Release(&pbin);
 		return NULL;
+	}
 	ascii_data = (unsigned char *)PyBytes_AS_STRING(rv);
 
 	/* Store the length */
@@ -312,6 +324,7 @@
 		Py_DECREF(rv);
 		rv = NULL;
 	}
+	PyBuffer_Release(&pbin);
 	return rv;
 }
 
@@ -346,6 +359,7 @@
 static PyObject *
 binascii_a2b_base64(PyObject *self, PyObject *args)
 {
+	Py_buffer pascii;
 	unsigned char *ascii_data, *bin_data;
 	int leftbits = 0;
 	unsigned char this_ch;
@@ -354,19 +368,25 @@
 	Py_ssize_t ascii_len, bin_len;
 	int quad_pos = 0;
 
-	if ( !PyArg_ParseTuple(args, "t#:a2b_base64", &ascii_data, &ascii_len) )
+	if ( !PyArg_ParseTuple(args, "y*:a2b_base64", &pascii) )
 		return NULL;
+	ascii_data = pascii.buf;
+	ascii_len = pascii.len;
 
 	assert(ascii_len >= 0);
 
-	if (ascii_len > PY_SSIZE_T_MAX - 3)
+	if (ascii_len > PY_SSIZE_T_MAX - 3) {
+		PyBuffer_Release(&pascii);
 		return PyErr_NoMemory();
+	}
 
 	bin_len = ((ascii_len+3)/4)*3; /* Upper bound, corrected later */
 
 	/* Allocate the buffer */
-	if ( (rv=PyBytes_FromStringAndSize(NULL, bin_len)) == NULL )
+	if ( (rv=PyBytes_FromStringAndSize(NULL, bin_len)) == NULL ) {
+		PyBuffer_Release(&pascii);
 		return NULL;
+	}
 	bin_data = (unsigned char *)PyBytes_AS_STRING(rv);
 	bin_len = 0;
 
@@ -419,6 +439,7 @@
  	}
 
 	if (leftbits != 0) {
+		PyBuffer_Release(&pascii);
 		PyErr_SetString(Error, "Incorrect padding");
 		Py_DECREF(rv);
 		return NULL;
@@ -438,6 +459,7 @@
 		Py_DECREF(rv);
 		rv = PyBytes_FromStringAndSize("", 0);
 	}
+	PyBuffer_Release(&pascii);
 	return rv;
 }
 
@@ -446,6 +468,7 @@
 static PyObject *
 binascii_b2a_base64(PyObject *self, PyObject *args)
 {
+	Py_buffer pbuf;
 	unsigned char *ascii_data, *bin_data;
 	int leftbits = 0;
 	unsigned char this_ch;
@@ -453,21 +476,26 @@
 	PyObject *rv;
 	Py_ssize_t bin_len;
 
-	if ( !PyArg_ParseTuple(args, "s#:b2a_base64", &bin_data, &bin_len) )
+	if ( !PyArg_ParseTuple(args, "s*:b2a_base64", &pbuf) )
 		return NULL;
+	bin_data = pbuf.buf;
+	bin_len = pbuf.len;
 
 	assert(bin_len >= 0);
 
 	if ( bin_len > BASE64_MAXBIN ) {
 		PyErr_SetString(Error, "Too much data for base64 line");
+		PyBuffer_Release(&pbuf);
 		return NULL;
 	}
 
 	/* We're lazy and allocate too much (fixed up later).
 	   "+3" leaves room for up to two pad characters and a trailing
 	   newline.  Note that 'b' gets encoded as 'Yg==\n' (1 in, 5 out). */
-	if ( (rv=PyBytes_FromStringAndSize(NULL, bin_len*2 + 3)) == NULL )
+	if ( (rv=PyBytes_FromStringAndSize(NULL, bin_len*2 + 3)) == NULL ) {
+		PyBuffer_Release(&pbuf);
 		return NULL;
+	}
 	ascii_data = (unsigned char *)PyBytes_AS_STRING(rv);
 
 	for( ; bin_len > 0 ; bin_len--, bin_data++ ) {
@@ -498,6 +526,7 @@
 		Py_DECREF(rv);
 		rv = NULL;
 	}
+	PyBuffer_Release(&pbuf);
 	return rv;
 }
 
@@ -581,22 +610,29 @@
 static PyObject *
 binascii_rlecode_hqx(PyObject *self, PyObject *args)
 {
+	Py_buffer pbuf;
 	unsigned char *in_data, *out_data;
 	PyObject *rv;
 	unsigned char ch;
 	Py_ssize_t in, inend, len;
 
-	if ( !PyArg_ParseTuple(args, "s#:rlecode_hqx", &in_data, &len) )
+	if ( !PyArg_ParseTuple(args, "s*:rlecode_hqx", &pbuf) )
 		return NULL;
+	in_data = pbuf.buf;
+	len = pbuf.len;
 
 	assert(len >= 0);
 
-	if (len > PY_SSIZE_T_MAX / 2 - 2)
+	if (len > PY_SSIZE_T_MAX / 2 - 2) {
+		PyBuffer_Release(&pbuf);
 		return PyErr_NoMemory();
+	}
 
 	/* Worst case: output is twice as big as input (fixed later) */
-	if ( (rv=PyBytes_FromStringAndSize(NULL, len*2+2)) == NULL )
+	if ( (rv=PyBytes_FromStringAndSize(NULL, len*2+2)) == NULL ) {
+		PyBuffer_Release(&pbuf);
 		return NULL;
+	}
 	out_data = (unsigned char *)PyBytes_AS_STRING(rv);
 
 	for( in=0; in<len; in++) {
@@ -629,6 +665,7 @@
 		Py_DECREF(rv);
 		rv = NULL;
 	}
+	PyBuffer_Release(&pbuf);
 	return rv;
 }
 
@@ -637,6 +674,7 @@
 static PyObject *
 binascii_b2a_hqx(PyObject *self, PyObject *args)
 {
+	Py_buffer pbin;
 	unsigned char *ascii_data, *bin_data;
 	int leftbits = 0;
 	unsigned char this_ch;
@@ -644,17 +682,23 @@
 	PyObject *rv;
 	Py_ssize_t len;
 
-	if ( !PyArg_ParseTuple(args, "s#:b2a_hqx", &bin_data, &len) )
+	if ( !PyArg_ParseTuple(args, "s*:b2a_hqx", &pbin) )
 		return NULL;
+	bin_data = pbin.buf;
+	len = pbin.len;
 
 	assert(len >= 0);
 
-	if (len > PY_SSIZE_T_MAX / 2 - 2)
+	if (len > PY_SSIZE_T_MAX / 2 - 2) {
+		PyBuffer_Release(&pbin);
 		return PyErr_NoMemory();
+	}
 
 	/* Allocate a buffer that is at least large enough */
-	if ( (rv=PyBytes_FromStringAndSize(NULL, len*2+2)) == NULL )
+	if ( (rv=PyBytes_FromStringAndSize(NULL, len*2+2)) == NULL ) {
+		PyBuffer_Release(&pbin);
 		return NULL;
+	}
 	ascii_data = (unsigned char *)PyBytes_AS_STRING(rv);
 
 	for( ; len > 0 ; len--, bin_data++ ) {
@@ -678,6 +722,7 @@
 		Py_DECREF(rv);
 		rv = NULL;
 	}
+	PyBuffer_Release(&pbin);
 	return rv;
 }
 
@@ -686,26 +731,35 @@
 static PyObject *
 binascii_rledecode_hqx(PyObject *self, PyObject *args)
 {
+	Py_buffer pin;
 	unsigned char *in_data, *out_data;
 	unsigned char in_byte, in_repeat;
 	PyObject *rv;
 	Py_ssize_t in_len, out_len, out_len_left;
 
-	if ( !PyArg_ParseTuple(args, "s#:rledecode_hqx", &in_data, &in_len) )
+	if ( !PyArg_ParseTuple(args, "s*:rledecode_hqx", &pin) )
 		return NULL;
+	in_data = pin.buf;
+	in_len = pin.len;
 
 	assert(in_len >= 0);
 
 	/* Empty string is a special case */
-	if ( in_len == 0 )
+	if ( in_len == 0 ) {
+		PyBuffer_Release(&pin);
 		return PyBytes_FromStringAndSize("", 0);
-	else if (in_len > PY_SSIZE_T_MAX / 2)
+	}
+	else if (in_len > PY_SSIZE_T_MAX / 2) {
+		PyBuffer_Release(&pin);
 		return PyErr_NoMemory();
+	}
 
 	/* Allocate a buffer of reasonable size. Resized when needed */
 	out_len = in_len*2;
-	if ( (rv=PyBytes_FromStringAndSize(NULL, out_len)) == NULL )
+	if ( (rv=PyBytes_FromStringAndSize(NULL, out_len)) == NULL ) {
+		PyBuffer_Release(&pin);
 		return NULL;
+	}
 	out_len_left = out_len;
 	out_data = (unsigned char *)PyBytes_AS_STRING(rv);
 
@@ -718,6 +772,7 @@
 	         if ( --in_len < 0 ) { \
 			   PyErr_SetString(Incomplete, ""); \
 			   Py_DECREF(rv); \
+			   PyBuffer_Release(&pin); \
 			   return NULL; \
 		 } \
 		 b = *in_data++; \
@@ -728,7 +783,7 @@
 		 if ( --out_len_left < 0 ) { \
 			  if ( out_len > PY_SSIZE_T_MAX / 2) return PyErr_NoMemory(); \
 			  if (_PyBytes_Resize(&rv, 2*out_len) < 0) \
-			    { Py_DECREF(rv); return NULL; } \
+			    { Py_DECREF(rv); PyBuffer_Release(&pin); return NULL; } \
 			  out_data = (unsigned char *)PyBytes_AS_STRING(rv) \
 								 + out_len; \
 			  out_len_left = out_len-1; \
@@ -783,6 +838,7 @@
 		Py_DECREF(rv);
 		rv = NULL;
 	}
+	PyBuffer_Release(&pin);
 	return rv;
 }
 
@@ -792,17 +848,21 @@
 static PyObject *
 binascii_crc_hqx(PyObject *self, PyObject *args)
 {
+	Py_buffer pin;
 	unsigned char *bin_data;
 	unsigned int crc;
 	Py_ssize_t len;
 
-	if ( !PyArg_ParseTuple(args, "s#i:crc_hqx", &bin_data, &len, &crc) )
+	if ( !PyArg_ParseTuple(args, "s*i:crc_hqx", &pin, &crc) )
 		return NULL;
+	bin_data = pin.buf;
+	len = pin.len;
 
 	while(len-- > 0) {
 		crc=((crc<<8)&0xff00)^crctab_hqx[((crc>>8)&0xff)^*bin_data++];
 	}
 
+	PyBuffer_Release(&pin);
 	return Py_BuildValue("i", crc);
 }
 
@@ -815,13 +875,17 @@
 binascii_crc32(PyObject *self, PyObject *args)
 {
     unsigned int crc32val = 0;  /* crc32(0L, Z_NULL, 0) */
+    Py_buffer pbuf;
     Byte *buf;
     Py_ssize_t len;
     int signed_val;
 
-    if (!PyArg_ParseTuple(args, "s#|I:crc32", &buf, &len, &crc32val))
+    if (!PyArg_ParseTuple(args, "s*|I:crc32", &pbuf, &crc32val))
         return NULL;
+    buf = (Byte*)pbuf.buf;
+    len = pbuf.len;
     signed_val = crc32(crc32val, buf, len);
+    PyBuffer_Release(&pbuf);
     return PyLong_FromUnsignedLong(signed_val & 0xffffffffU);
 }
 #else  /* USE_ZLIB_CRC32 */
@@ -946,13 +1010,16 @@
 static PyObject *
 binascii_crc32(PyObject *self, PyObject *args)
 { /* By Jim Ahlstrom; All rights transferred to CNRI */
+	Py_buffer pbin;
 	unsigned char *bin_data;
 	unsigned int crc = 0;	/* initial value of CRC */
 	Py_ssize_t len;
 	unsigned int result;
 
-	if ( !PyArg_ParseTuple(args, "s#|I:crc32", &bin_data, &len, &crc) )
+	if ( !PyArg_ParseTuple(args, "s*|I:crc32", &pbin, &crc) )
 		return NULL;
+	bin_data = pbin.buf;
+	len = pbin.len;
 
 	crc = ~ crc;
 	while (len-- > 0) {
@@ -961,6 +1028,7 @@
 	}
 
 	result = (crc ^ 0xFFFFFFFF);
+	PyBuffer_Release(&pbuf);
 	return PyLong_FromUnsignedLong(result & 0xffffffff);
 }
 #endif  /* USE_ZLIB_CRC32 */
@@ -969,22 +1037,29 @@
 static PyObject *
 binascii_hexlify(PyObject *self, PyObject *args)
 {
+	Py_buffer parg;
 	char* argbuf;
 	Py_ssize_t arglen;
 	PyObject *retval;
 	char* retbuf;
 	Py_ssize_t i, j;
 
-	if (!PyArg_ParseTuple(args, "s#:b2a_hex", &argbuf, &arglen))
+	if (!PyArg_ParseTuple(args, "s*:b2a_hex", &parg))
 		return NULL;
+	argbuf = parg.buf;
+	arglen = parg.len;
 
 	assert(arglen >= 0);
-	if (arglen > PY_SSIZE_T_MAX / 2)
+	if (arglen > PY_SSIZE_T_MAX / 2) {
+		PyBuffer_Release(&parg);
 		return PyErr_NoMemory();
+	}
 
 	retval = PyBytes_FromStringAndSize(NULL, arglen*2);
-	if (!retval)
+	if (!retval) {
+		PyBuffer_Release(&parg);
 		return NULL;
+	}
 	retbuf = PyBytes_AS_STRING(retval);
 
 	/* make hex version of string, taken from shamodule.c */
@@ -997,6 +1072,7 @@
 		c = (c>9) ? c+'a'-10 : c + '0';
 		retbuf[j++] = c;
 	}
+	PyBuffer_Release(&parg);
 	return retval;
 }
 
@@ -1024,14 +1100,17 @@
 static PyObject *
 binascii_unhexlify(PyObject *self, PyObject *args)
 {
+	Py_buffer parg;
 	char* argbuf;
 	Py_ssize_t arglen;
 	PyObject *retval;
 	char* retbuf;
 	Py_ssize_t i, j;
 
-	if (!PyArg_ParseTuple(args, "s#:a2b_hex", &argbuf, &arglen))
+	if (!PyArg_ParseTuple(args, "s*:a2b_hex", &parg))
 		return NULL;
+	argbuf = parg.buf;
+	arglen = parg.len;
 
 	assert(arglen >= 0);
 
@@ -1040,13 +1119,16 @@
 	 * raise an exception.
 	 */
 	if (arglen % 2) {
+		PyBuffer_Release(&parg);
 		PyErr_SetString(Error, "Odd-length string");
 		return NULL;
 	}
 
 	retval = PyBytes_FromStringAndSize(NULL, (arglen/2));
-	if (!retval)
+	if (!retval) {
+		PyBuffer_Release(&parg);
 		return NULL;
+	}
 	retbuf = PyBytes_AS_STRING(retval);
 
 	for (i=j=0; i < arglen; i += 2) {
@@ -1059,9 +1141,11 @@
 		}
 		retbuf[j++] = (top << 4) + bot;
 	}
+	PyBuffer_Release(&parg);
 	return retval;
 
   finally:
+	PyBuffer_Release(&parg);
 	Py_DECREF(retval);
 	return NULL;
 }
@@ -1094,15 +1178,18 @@
 {
 	Py_ssize_t in, out;
 	char ch;
+	Py_buffer pdata;
 	unsigned char *data, *odata;
 	Py_ssize_t datalen = 0;
 	PyObject *rv;
 	static char *kwlist[] = {"data", "header", NULL};
 	int header = 0;
 
-	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s#|i", kwlist, &data,
-	      &datalen, &header))
+	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s*|i", kwlist, &pdata,
+	      &header))
 		return NULL;
+	data = pdata.buf;
+	datalen = pdata.len;
 
 	/* We allocate the output same size as input, this is overkill.
 	 * The previous implementation used calloc() so we'll zero out the
@@ -1110,6 +1197,7 @@
 	 */
 	odata = (unsigned char *) PyMem_Malloc(datalen);
 	if (odata == NULL) {
+		PyBuffer_Release(&pdata);
 		PyErr_NoMemory();
 		return NULL;
 	}
@@ -1160,9 +1248,11 @@
 		}
 	}
 	if ((rv = PyBytes_FromStringAndSize((char *)odata, out)) == NULL) {
+		PyBuffer_Release(&pdata);
 		PyMem_Free(odata);
 		return NULL;
 	}
+	PyBuffer_Release(&pdata);
 	PyMem_Free(odata);
 	return rv;
 }
@@ -1193,6 +1283,7 @@
 binascii_b2a_qp (PyObject *self, PyObject *args, PyObject *kwargs)
 {
 	Py_ssize_t in, out;
+	Py_buffer pdata;
 	unsigned char *data, *odata;
 	Py_ssize_t datalen = 0, odatalen = 0;
 	PyObject *rv;
@@ -1206,9 +1297,11 @@
 	int crlf = 0;
 	unsigned char *p;
 
-	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s#|iii", kwlist, &data,
-	      &datalen, &quotetabs, &istext, &header))
+	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s*|iii", kwlist, &pdata,
+	      &quotetabs, &istext, &header))
 		return NULL;
+	data = pdata.buf;
+	datalen = pdata.len;
 
 	/* See if this string is using CRLF line ends */
 	/* XXX: this function has the side effect of converting all of
@@ -1286,6 +1379,7 @@
 	 */
 	odata = (unsigned char *) PyMem_Malloc(odatalen);
 	if (odata == NULL) {
+		PyBuffer_Release(&pdata);
 		PyErr_NoMemory();
 		return NULL;
 	}
@@ -1360,9 +1454,11 @@
 		}
 	}
 	if ((rv = PyBytes_FromStringAndSize((char *)odata, out)) == NULL) {
+		PyBuffer_Release(&pdata);
 		PyMem_Free(odata);
 		return NULL;
 	}
+	PyBuffer_Release(&pdata);
 	PyMem_Free(odata);
 	return rv;
 }
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;
 }
diff --git a/Modules/cjkcodecs/multibytecodec.c b/Modules/cjkcodecs/multibytecodec.c
index dbd5314..95b2278 100644
--- a/Modules/cjkcodecs/multibytecodec.c
+++ b/Modules/cjkcodecs/multibytecodec.c
@@ -608,18 +608,24 @@
 	MultibyteCodec_State state;
 	MultibyteDecodeBuffer buf;
 	PyObject *errorcb;
+	Py_buffer pdata;
 	const char *data, *errors = NULL;
 	Py_ssize_t datalen, finalsize;
 
-	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s#|z:decode",
-				codeckwarglist, &data, &datalen, &errors))
+	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s*|z:decode",
+				codeckwarglist, &pdata, &errors))
 		return NULL;
+	data = pdata.buf;
+	datalen = pdata.len;
 
 	errorcb = internal_error_callback(errors);
-	if (errorcb == NULL)
+	if (errorcb == NULL) {
+		PyBuffer_Release(&pdata);
 		return NULL;
+	}
 
 	if (datalen == 0) {
+		PyBuffer_Release(&pdata);
 		ERROR_DECREF(errorcb);
 		return make_tuple(PyUnicode_FromUnicode(NULL, 0), 0);
 	}
@@ -659,11 +665,13 @@
 		if (PyUnicode_Resize(&buf.outobj, finalsize) == -1)
 			goto errorexit;
 
+	PyBuffer_Release(&pdata);
 	Py_XDECREF(buf.excobj);
 	ERROR_DECREF(errorcb);
 	return make_tuple(buf.outobj, datalen);
 
 errorexit:
+	PyBuffer_Release(&pdata);
 	ERROR_DECREF(errorcb);
 	Py_XDECREF(buf.excobj);
 	Py_XDECREF(buf.outobj);
diff --git a/Modules/fcntlmodule.c b/Modules/fcntlmodule.c
index 46bf4d1..5331ea8 100644
--- a/Modules/fcntlmodule.c
+++ b/Modules/fcntlmodule.c
@@ -113,15 +113,18 @@
 	unsigned int code;
 	int arg;
 	int ret;
+	Py_buffer pstr;
 	char *str;
 	Py_ssize_t len;
 	int mutate_arg = 1;
  	char buf[IOCTL_BUFSZ+1];  /* argument plus NUL byte */
 
-	if (PyArg_ParseTuple(args, "O&Iw#|i:ioctl",
+	if (PyArg_ParseTuple(args, "O&Iw*|i:ioctl",
                              conv_descriptor, &fd, &code, 
-			     &str, &len, &mutate_arg)) {
+			     &pstr, &mutate_arg)) {
 		char *arg;
+		str = pstr.buf;
+		len = pstr.len;
 
 	       	if (mutate_arg) {
 			if (len <= IOCTL_BUFSZ) {
@@ -135,6 +138,7 @@
 		}
 		else {
 			if (len > IOCTL_BUFSZ) {
+				PyBuffer_Release(&pstr);
 				PyErr_SetString(PyExc_ValueError,
 					"ioctl string arg too long");
 				return NULL;
@@ -156,6 +160,7 @@
 		if (mutate_arg && (len < IOCTL_BUFSZ)) {
 			memcpy(str, buf, len);
 		}
+		PyBuffer_Release(&pstr); /* No further access to str below this point */
 		if (ret < 0) {
 			PyErr_SetFromErrno(PyExc_IOError);
 			return NULL;
@@ -169,9 +174,12 @@
 	}
 
 	PyErr_Clear();
-	if (PyArg_ParseTuple(args, "O&Is#:ioctl",
-                             conv_descriptor, &fd, &code, &str, &len)) {
+	if (PyArg_ParseTuple(args, "O&Is*:ioctl",
+                             conv_descriptor, &fd, &code, &pstr)) {
+		str = pstr.buf;
+		len = pstr.len;
 		if (len > IOCTL_BUFSZ) {
+			PyBuffer_Release(&pstr);
 			PyErr_SetString(PyExc_ValueError,
 					"ioctl string arg too long");
 			return NULL;
@@ -182,9 +190,11 @@
 		ret = ioctl(fd, code, buf);
 		Py_END_ALLOW_THREADS
 		if (ret < 0) {
+			PyBuffer_Release(&pstr);
 			PyErr_SetFromErrno(PyExc_IOError);
 			return NULL;
 		}
+		PyBuffer_Release(&pstr);
 		return PyBytes_FromStringAndSize(buf, len);
 	}
 
diff --git a/Modules/mmapmodule.c b/Modules/mmapmodule.c
index 51ad69c..c8dfc24 100644
--- a/Modules/mmapmodule.c
+++ b/Modules/mmapmodule.c
@@ -651,7 +651,7 @@
 mmap_buffer_getbuf(mmap_object *self, Py_buffer *view, int flags)
 {
 	CHECK_VALID(-1);
-        if (PyBuffer_FillInfo(view, self->data, self->size,
+        if (PyBuffer_FillInfo(view, (PyObject*)self, self->data, self->size,
                               (self->access == ACCESS_READ), flags) < 0)
                 return -1;
         self->exports++;
@@ -843,7 +843,7 @@
 		if (vbuf.len != slicelen) {
 			PyErr_SetString(PyExc_IndexError,
 				"mmap slice assignment is wrong size");
-			PyObject_ReleaseBuffer(value, &vbuf);
+			PyBuffer_Release(&vbuf);
 			return -1;
 		}
 
@@ -862,7 +862,7 @@
 				self->data[cur] = ((char *)vbuf.buf)[i];
 			}
 		}
-		PyObject_ReleaseBuffer(value, &vbuf);
+		PyBuffer_Release(&vbuf);
 		return 0;
 	}
 	else {
diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c
index 3b79d05..b499b47 100644
--- a/Modules/posixmodule.c
+++ b/Modules/posixmodule.c
@@ -4894,15 +4894,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 PyLong_FromSsize_t(size);
diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c
index de802ae..7d91af2 100644
--- a/Modules/socketmodule.c
+++ b/Modules/socketmodule.c
@@ -2251,15 +2251,19 @@
 
 	int recvlen = 0, flags = 0;
         ssize_t readlen;
+	Py_buffer pbuf;
 	char *buf;
 	int buflen;
 
 	/* Get the buffer's memory */
-	if (!PyArg_ParseTupleAndKeywords(args, kwds, "w#|ii:recv_into", kwlist,
-					 &buf, &buflen, &recvlen, &flags))
+	if (!PyArg_ParseTupleAndKeywords(args, kwds, "w*|ii:recv_into", kwlist,
+					 &pbuf, &recvlen, &flags))
 		return NULL;
+	buf = pbuf.buf;
+	buflen = pbuf.len;
 
 	if (recvlen < 0) {
+		PyBuffer_Release(&pbuf);
 		PyErr_SetString(PyExc_ValueError,
 				"negative buffersize in recv_into");
 		return NULL;
@@ -2271,6 +2275,7 @@
 
 	/* Check if the buffer is large enough */
 	if (buflen < recvlen) {
+		PyBuffer_Release(&pbuf);
 		PyErr_SetString(PyExc_ValueError,
 				"buffer too small for requested bytes");
 		return NULL;
@@ -2280,9 +2285,11 @@
 	readlen = sock_recv_guts(s, buf, recvlen, flags);
 	if (readlen < 0) {
 		/* Return an error. */
+		PyBuffer_Release(&pbuf);
 		return NULL;
 	}
 
+	PyBuffer_Release(&pbuf);
 	/* Return the number of bytes read.  Note that we do not do anything
 	   special here in the case that readlen < recvlen. */
 	return PyLong_FromSsize_t(readlen);
@@ -2424,18 +2431,22 @@
 
 	int recvlen = 0, flags = 0;
         ssize_t readlen;
+	Py_buffer pbuf;
 	char *buf;
 	int buflen;
 
 	PyObject *addr = NULL;
 
-	if (!PyArg_ParseTupleAndKeywords(args, kwds, "w#|ii:recvfrom_into",
-					 kwlist, &buf, &buflen,
+	if (!PyArg_ParseTupleAndKeywords(args, kwds, "w*|ii:recvfrom_into",
+					 kwlist, &pbuf,
 					 &recvlen, &flags))
 		return NULL;
+	buf = pbuf.buf;
+	buflen = pbuf.len;
 	assert(buf != 0 && buflen > 0);
 
 	if (recvlen < 0) {
+		PyBuffer_Release(&pbuf);
 		PyErr_SetString(PyExc_ValueError,
 				"negative buffersize in recvfrom_into");
 		return NULL;
@@ -2447,11 +2458,13 @@
 
 	readlen = sock_recvfrom_guts(s, buf, recvlen, flags, &addr);
 	if (readlen < 0) {
+		PyBuffer_Release(&pbuf);
 		/* Return an error */
 		Py_XDECREF(addr);
 		return NULL;
 	}
 
+	PyBuffer_Release(&pbuf);
 	/* Return the number of bytes read and the address.  Note that we do
 	   not do anything special here in the case that readlen < recvlen. */
  	return Py_BuildValue("lN", readlen, addr);
@@ -2470,12 +2483,17 @@
 {
 	char *buf;
 	int len, n = -1, flags = 0, timeout;
+	Py_buffer pbuf;
 
-	if (!PyArg_ParseTuple(args, "y#|i:send", &buf, &len, &flags))
+	if (!PyArg_ParseTuple(args, "y*|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);
@@ -2487,6 +2505,8 @@
 #endif
 	Py_END_ALLOW_THREADS
 
+	PyBuffer_Release(&pbuf);
+
 	if (timeout == 1) {
 		PyErr_SetString(socket_timeout, "timed out");
 		return NULL;
@@ -2511,12 +2531,17 @@
 {
 	char *buf;
 	int len, n = -1, flags = 0, timeout;
+	Py_buffer pbuf;
 
-	if (!PyArg_ParseTuple(args, "y#|i:sendall", &buf, &len, &flags))
+	if (!PyArg_ParseTuple(args, "y*|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 {
@@ -2535,6 +2560,7 @@
 		len -= n;
 	} while (len > 0);
 	Py_END_ALLOW_THREADS
+	PyBuffer_Release(&pbuf);
 
 	if (timeout == 1) {
 		PyErr_SetString(socket_timeout, "timed out");
@@ -2561,24 +2587,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, "y#O:sendto", &buf, &len, &addro)) {
+	if (!PyArg_ParseTuple(args, "y*O:sendto", &pbuf, &addro)) {
 		PyErr_Clear();
-		if (!PyArg_ParseTuple(args, "y#iO:sendto",
-				      &buf, &len, &flags, &addro))
+		if (!PyArg_ParseTuple(args, "y*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);
@@ -2586,6 +2620,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;
diff --git a/Modules/zlibmodule.c b/Modules/zlibmodule.c
index b6f324b..3fa84d9 100644
--- a/Modules/zlibmodule.c
+++ b/Modules/zlibmodule.c
@@ -118,18 +118,22 @@
 PyZlib_compress(PyObject *self, PyObject *args)
 {
     PyObject *ReturnVal = NULL;
+    Py_buffer pinput;
     Byte *input, *output;
     int length, level=Z_DEFAULT_COMPRESSION, err;
     z_stream zst;
 
     /* require Python string object, optional 'level' arg */
-    if (!PyArg_ParseTuple(args, "s#|i:compress", &input, &length, &level))
+    if (!PyArg_ParseTuple(args, "s*|i:compress", &pinput, &level))
 	return NULL;
+    input = pinput.buf;
+    length = pinput.len;
 
     zst.avail_out = length + length/1000 + 12 + 1;
 
     output = (Byte*)malloc(zst.avail_out);
     if (output == NULL) {
+	PyBuffer_Release(&pinput);
 	PyErr_SetString(PyExc_MemoryError,
 			"Can't allocate memory to compress data");
 	return NULL;
@@ -180,6 +184,7 @@
 	zlib_error(zst, err, "while finishing compression");
 
  error:
+    PyBuffer_Release(&pinput);
     free(output);
 
     return ReturnVal;
@@ -195,15 +200,18 @@
 PyZlib_decompress(PyObject *self, PyObject *args)
 {
     PyObject *result_str;
+    Py_buffer pinput;
     Byte *input;
     int length, err;
     int wsize=DEF_WBITS;
     Py_ssize_t r_strlen=DEFAULTALLOC;
     z_stream zst;
 
-    if (!PyArg_ParseTuple(args, "s#|in:decompress",
-			  &input, &length, &wsize, &r_strlen))
+    if (!PyArg_ParseTuple(args, "s*|in:decompress",
+			  &pinput, &wsize, &r_strlen))
 	return NULL;
+    input = pinput.buf;
+    length = pinput.len;
 
     if (r_strlen <= 0)
 	r_strlen = 1;
@@ -211,8 +219,10 @@
     zst.avail_in = length;
     zst.avail_out = r_strlen;
 
-    if (!(result_str = PyByteArray_FromStringAndSize(NULL, r_strlen)))
+    if (!(result_str = PyByteArray_FromStringAndSize(NULL, r_strlen))) {
+	PyBuffer_Release(&pinput);
 	return NULL;
+    }
 
     zst.zalloc = (alloc_func)NULL;
     zst.zfree = (free_func)Z_NULL;
@@ -281,9 +291,11 @@
     if (PyByteArray_Resize(result_str, zst.total_out) < 0)
         goto error;
 
+    PyBuffer_Release(&pinput);
     return result_str;
 
  error:
+    PyBuffer_Release(&pinput);
     Py_XDECREF(result_str);
     return NULL;
 }
@@ -396,14 +408,19 @@
 {
     int err, inplen, length = DEFAULTALLOC;
     PyObject *RetVal;
+    Py_buffer pinput;
     Byte *input;
     unsigned long start_total_out;
 
-    if (!PyArg_ParseTuple(args, "s#:compress", &input, &inplen))
+    if (!PyArg_ParseTuple(args, "s*:compress", &pinput))
 	return NULL;
+    input = pinput.buf;
+    inplen = pinput.len;
 
-    if (!(RetVal = PyByteArray_FromStringAndSize(NULL, length)))
+    if (!(RetVal = PyByteArray_FromStringAndSize(NULL, length))) {
+	PyBuffer_Release(&pinput);
 	return NULL;
+    }
 
     ENTER_ZLIB
 
@@ -452,6 +469,7 @@
 
  error:
     LEAVE_ZLIB
+    PyBuffer_Release(&pinput);
     return RetVal;
 }
 
@@ -472,13 +490,17 @@
     int err, inplen, old_length, length = DEFAULTALLOC;
     int max_length = 0;
     PyObject *RetVal;
+    Py_buffer pinput;
     Byte *input;
     unsigned long start_total_out;
 
-    if (!PyArg_ParseTuple(args, "s#|i:decompress", &input,
-			  &inplen, &max_length))
+    if (!PyArg_ParseTuple(args, "s*|i:decompress", &pinput,
+			  &max_length))
 	return NULL;
+    input = pinput.buf;
+    inplen = pinput.len;
     if (max_length < 0) {
+	PyBuffer_Release(&pinput);
 	PyErr_SetString(PyExc_ValueError,
 			"max_length must be greater than zero");
 	return NULL;
@@ -487,8 +509,10 @@
     /* limit amount of data allocated to max_length */
     if (max_length && length > max_length)
 	length = max_length;
-    if (!(RetVal = PyByteArray_FromStringAndSize(NULL, length)))
+    if (!(RetVal = PyByteArray_FromStringAndSize(NULL, length))) {
+	PyBuffer_Release(&pinput);
 	return NULL;
+    }
 
     ENTER_ZLIB
 
@@ -577,7 +601,7 @@
 
  error:
     LEAVE_ZLIB
-
+    PyBuffer_Release(&pinput);
     return RetVal;
 }
 
@@ -916,12 +940,13 @@
 PyZlib_crc32(PyObject *self, PyObject *args)
 {
     unsigned int crc32val = 0;  /* crc32(0L, Z_NULL, 0) */
-    Byte *buf;
-    int len, signed_val;
+    Py_buffer pbuf;
+    int signed_val;
 
-    if (!PyArg_ParseTuple(args, "s#|I:crc32", &buf, &len, &crc32val))
+    if (!PyArg_ParseTuple(args, "s*|I:crc32", &pbuf, &crc32val))
 	return NULL;
-    signed_val = crc32(crc32val, buf, len);
+    signed_val = crc32(crc32val, pbuf.buf, pbuf.len);
+    PyBuffer_Release(&pbuf);
     return PyLong_FromUnsignedLong(signed_val & 0xffffffffU);
 }