]> granicus.if.org Git - python/commitdiff
Merged revisions 65654 via svnmerge from
authorMartin v. Löwis <martin@v.loewis.de>
Wed, 13 Aug 2008 15:53:07 +0000 (15:53 +0000)
committerMartin v. Löwis <martin@v.loewis.de>
Wed, 13 Aug 2008 15:53:07 +0000 (15:53 +0000)
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*.
........

32 files changed:
Doc/c-api/arg.rst
Doc/whatsnew/2.6.rst
Include/abstract.h
Include/object.h
Lib/test/test_sys.py
Modules/_bsddb.c
Modules/_codecsmodule.c
Modules/_ctypes/_ctypes.c
Modules/_fileio.c
Modules/_hashopenssl.c
Modules/_json.c
Modules/_multiprocessing/connection.h
Modules/_sre.c
Modules/_struct.c
Modules/arraymodule.c
Modules/audioop.c
Modules/binascii.c
Modules/bz2module.c
Modules/cjkcodecs/multibytecodec.c
Modules/fcntlmodule.c
Modules/mmapmodule.c
Modules/posixmodule.c
Modules/socketmodule.c
Modules/zlibmodule.c
Objects/abstract.c
Objects/bytearrayobject.c
Objects/bytesobject.c
Objects/memoryobject.c
Objects/unicodeobject.c
PC/winreg.c
Python/getargs.c
Python/marshal.c

index faf97edecb9f49c2470bb59e2e98ef10339c0995..de7b930d0f4d052f3f4fd9cbeba7d0fc4f4b371e 100644 (file)
@@ -40,6 +40,12 @@ variable(s) whose address should be passed.
    other read-buffer compatible objects pass back a reference to the raw internal
    data representation.
 
+``s*`` (string, Unicode, or any buffer compatible object) [Py_buffer \*]
+  Similar to ``s#``, this code fills a Py_buffer structure provided by the caller.
+  The buffer gets locked, so that the caller can subsequently use the buffer even
+  inside a ``Py_BEGIN_ALLOW_THREADS`` block; the caller is responsible for calling
+  ``PyBuffer_Release`` with the structure after it has processed the data.
+
 ``y`` (bytes object) [const char \*]
    This variant on ``s`` convert a Python bytes object to a C pointer to a
    character string. The bytes object must not contain embedded NUL bytes; if it
@@ -49,6 +55,9 @@ variable(s) whose address should be passed.
    This variant on ``s#`` stores into two C variables, the first one a pointer to a
    character string, the second one its length.  This only accepts bytes objects.
 
+``y*`` (bytes object) [Py_buffer \*]
+   This is to ``s*`` as ``y`` is to ``s``.
+
 ``z`` (string or ``None``) [const char \*]
    Like ``s``, but the Python object may also be ``None``, in which case the C
    pointer is set to *NULL*.
@@ -56,6 +65,9 @@ variable(s) whose address should be passed.
 ``z#`` (string or ``None`` or any read buffer compatible object) [const char \*, int]
    This is to ``s#`` as ``z`` is to ``s``.
 
+``z*`` (string or ``None`` or any buffer compatible object) [Py_buffer*]
+   This is to ``s*`` as ``z`` is to ``s``.
+
 ``u`` (Unicode object) [Py_UNICODE \*]
    Convert a Python Unicode object to a C pointer to a NUL-terminated buffer of
    16-bit Unicode (UTF-16) data.  As with ``s``, there is no need to provide
@@ -244,6 +256,9 @@ variable(s) whose address should be passed.
    single-segment buffer objects are accepted; :exc:`TypeError` is raised for all
    others.
 
+``w*`` (read-write byte-oriented buffer) [Py_buffer \*]
+   This is to ``w`` what ``s*`` is to ``s``.
+
 ``(items)`` (tuple) [*matching-items*]
    The object must be a Python sequence whose length is the number of format units
    in *items*.  The C arguments must correspond to the individual format units in
index c0ecf01292931dafd2ef7d518b2d6d5b1cebe053..0f8b88325c8ba9f88b0a5434b0d2f896660cc754 100644 (file)
@@ -1064,7 +1064,7 @@ about the object's memory representation.  Objects
 can use this operation to lock memory in place
 while an external caller could be modifying the contents,
 so there's a corresponding
-``PyObject_ReleaseBuffer(PyObject *obj, Py_buffer *view)`` to
+``PyBuffer_Release(Py_buffer *view)`` to
 indicate that the external caller is done.
 
 The **flags** argument to :cfunc:`PyObject_GetBuffer` specifies
@@ -2841,7 +2841,7 @@ Changes to Python's build process and to the C API include:
 
 * The new buffer interface, previously described in
   `the PEP 3118 section <#pep-3118-revised-buffer-protocol>`__,
-  adds :cfunc:`PyObject_GetBuffer` and :cfunc:`PyObject_ReleaseBuffer`,
+  adds :cfunc:`PyObject_GetBuffer` and :cfunc:`PyBuffer_Release`,
   as well as a few other functions.
 
 * Python's use of the C stdio library is now thread-safe, or at least
index 9a1003b379101638ffcc7cd95b5b8409dc171bd7..46a6f544a344b13f0a19d6bddc86c90b146e81c1 100644 (file)
@@ -526,24 +526,6 @@ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/
         */
 
 
-     PyAPI_FUNC(void) PyObject_ReleaseBuffer(PyObject *obj, Py_buffer *view);
-
-
-       /* C-API version of the releasebuffer function call.  It
-          checks to make sure the object has the required function
-          pointer and issues the call.  The obj must have the buffer
-          interface or this function will cause a segfault (i.e. it
-          is assumed to be called only after a corresponding
-          getbuffer which already verified the existence of the
-          tp_as_buffer pointer).
-           
-           Returns 0 on success and -1 (with an error raised) on
-           failure.  This function always succeeds (as a NO-OP) if
-           there is no releasebuffer function for the object so that
-           it can always be called when the consumer is done with the
-           buffer
-        */
-
      PyAPI_FUNC(void *) PyBuffer_GetPointer(Py_buffer *view, Py_ssize_t *indices);
         
         /* Get the memory area pointed to by the indices for the buffer given. 
@@ -600,7 +582,7 @@ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/
             per element.
         */
 
-     PyAPI_FUNC(int) PyBuffer_FillInfo(Py_buffer *view, void *buf,
+     PyAPI_FUNC(int) PyBuffer_FillInfo(Py_buffer *view, PyObject *o, void *buf,
                                       Py_ssize_t len, int readonly,
                                       int flags);
 
@@ -610,6 +592,10 @@ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/
            and -1 (with raising an error) on error.
          */
 
+     PyAPI_FUNC(void) PyBuffer_Release(Py_buffer *view);
+
+       /* Releases a Py_buffer obtained from getbuffer ParseTuple's s*.
+        */
 
      PyAPI_FUNC(PyObject *) PyObject_Format(PyObject* obj,
                                            PyObject *format_spec);
index f5ec7d49a72291dc68e4b39d45a43afcf10cc93d..372eada548da26f81f5691a40922aecf12197b99 100644 (file)
@@ -142,7 +142,8 @@ typedef int(*objobjargproc)(PyObject *, PyObject *, PyObject *);
 
 /* buffer interface */
 typedef struct bufferinfo {
-       void *buf;         
+       void *buf;   
+       PyObject *obj;        /* borrowed reference */
         Py_ssize_t len;
         Py_ssize_t itemsize;  /* This is Py_ssize_t so it can be 
                                  pointed to by strides in simple case.*/
index f3c72e7c935bd9a2942fcc3f913cd67f0bcf2e23..04288d9fd67a254bac8f3ce60027ceb796da661b 100644 (file)
@@ -550,7 +550,7 @@ class SizeofTest(unittest.TestCase):
         check(32768*32768-1, size(vh) + 2*self.H)
         check(32768*32768, size(vh) + 3*self.H)
         # memory
-        check(memoryview(b''), size(h + 'P P2P2i5P'))
+        check(memoryview(b''), size(h + 'P PP2P2i5P'))
         # module
         check(unittest, size(h + '3P'))
         # None
index 648fb0da99ff63de8554f8bca7cf72b5182ff10c..7c0eae308363ac76ac6be470591d8d25d4e60769 100644 (file)
@@ -288,7 +288,7 @@ static void free_dbt(DBT *dbt)
 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 @@ static Py_buffer * _malloc_view(PyObject *obj)
     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;
     }
index 96dfd564e294aec08c28c2c55def0ccbc6b4cbc1..5026c05897bd75f2c4a6e21636b41bb6d2619f92 100644 (file)
@@ -252,20 +252,20 @@ static PyObject *
 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 @@ static PyObject *
 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 @@ static PyObject *
 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 @@ static PyObject *
 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 @@ static PyObject *
 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 @@ static PyObject *
 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 @@ static PyObject *
 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 @@ static PyObject *
 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 @@ static PyObject *
 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 @@ static PyObject *
 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 @@ static PyObject *
 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 *
index 02a08a40c45709e547097bce00a5eca4db7554cf..7ef3ea1df0df048e27c4705a3ee648de41fb793f 100644 (file)
@@ -1050,10 +1050,10 @@ CharArray_set_raw(CDataObject *self, PyObject *value)
 
        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 @@ static int CData_GetBuffer(PyObject *_self, Py_buffer *view, int flags)
        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 */
index f520f0c701fc149ca1c0dc5f3f05c71eac35da27..f0c8fedc3324839341bab276613c7c288cdd4089 100644 (file)
@@ -357,7 +357,7 @@ fileio_seekable(PyFileIOObject *self)
 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 @@ fileio_readinto(PyFileIOObject *self, PyObject *args)
        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 @@ fileio_read(PyFileIOObject *self, PyObject *args)
 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;
index bd04411113b8113c72d42a94ea3ebfe8dc335e88..c0f9a2cf924622a265b86fdb16499023944ad1b5 100644 (file)
@@ -164,7 +164,7 @@ EVP_hexdigest(EVPobject *self, PyObject *unused)
                 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_update(EVPobject *self, PyObject *args)
     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 @@ EVP_tp_init(EVPobject *self, PyObject *args, PyObject *kwds)
     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 @@ EVP_tp_init(EVPobject *self, PyObject *args, PyObject *kwds)
     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 @@ EVP_tp_init(EVPobject *self, PyObject *args, PyObject *kwds)
     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 @@ EVP_new(PyObject *self, PyObject *args, PyObject *kwdict)
                         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 @@ EVP_new(PyObject *self, PyObject *args, PyObject *kwdict)
                     Py_SAFE_DOWNCAST(view.len, Py_ssize_t, unsigned int)); \
      \
         if (data_obj) \
-            PyObject_ReleaseBuffer(data_obj, &view); \
+            PyBuffer_Release(&view); \
         return ret_obj; \
     }
 
index 1cf1e63cd586942bfecf86a04a5c76ba4c0b73b0..a724f89053f278a9457ec3f1ac844df73513a8b9 100644 (file)
@@ -261,7 +261,7 @@ scanstring_str(PyObject *pystr, Py_ssize_t end, char *encoding, int strict)
         /* 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);
index d651a97f3478a32ae6f532d9350f357a5a2d592c..e422d6999f4b7eb58fc8d561440815bae4aac293 100644 (file)
@@ -96,21 +96,26 @@ connection_dealloc(ConnectionObject* self)
 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 @@ connection_sendbytes(ConnectionObject *self, PyObject *args)
                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 @@ connection_sendbytes(ConnectionObject *self, PyObject *args)
 
        res = conn_send_string(self, buffer + offset, size);
 
+       PyBuffer_Release(&pbuffer);
        if (res < 0)
                return mp_SetError(PyExc_IOError, res);
 
@@ -187,21 +195,25 @@ connection_recvbytes_into(ConnectionObject *self, PyObject *args)
        char *freeme = NULL, *buffer = NULL;
        Py_ssize_t res, length, offset = 0;
        PyObject *result = NULL;
+       Py_buffer pbuf;
 
-       if (!PyArg_ParseTuple(args, "w#|" F_PY_SSIZE_T, 
-                             &buffer, &length, &offset))
+       CHECK_READABLE(self);
+       
+       if (!PyArg_ParseTuple(args, "w*|" F_PY_SSIZE_T, 
+                             &pbuf, &offset))
                return NULL;
 
-       CHECK_READABLE(self);
+       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 @@ connection_recvbytes_into(ConnectionObject *self, PyObject *args)
                                PyErr_SetObject(BufferTooShort, result);
                                Py_DECREF(result);
                        }
-                       return NULL;
+                       goto _error;
                }
        }
 
+_cleanup:
+       PyBuffer_Release(&pbuf);
        return result;
+
+_error:
+       result = NULL;
+       goto _cleanup;
 }
 
 /*
index 4511c1b802f396d9f78bf374ab5608b1508e3c9f..64fc5132c8262a241391e3b8d171623855d363fd 100644 (file)
@@ -1704,7 +1704,7 @@ getstring(PyObject* string, Py_ssize_t* p_length, int* p_charsize)
     /* 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");
index 43be9ed0a54ad3dfd06a31ca01096f635cd9bf15..4a257c0097036c10c7162bde81808f6b114d3de6 100644 (file)
@@ -1567,11 +1567,11 @@ s_unpack(PyObject *self, PyObject *input)
                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 @@ s_unpack_from(PyObject *self, PyObject *args, PyObject *kwds)
                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;
 }
 
index b5f819e2e35a8ba9dec97bf26a07b04e9e9d37dc..16a7a7e198387ef248ebbd0ebea842dccd0cc994 100644 (file)
@@ -1820,6 +1820,8 @@ array_buffer_getbuf(arrayobject *self, Py_buffer *view, int flags)
         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;
index c54e51255bd673c7ed90d606c059a0a753909a39..b2fdb9a3c72ec1613862acbfbcdef8c6706381c1 100644 (file)
@@ -783,20 +783,24 @@ audioop_mul(PyObject *self, PyObject *args)
 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 @@ audioop_tomono(PyObject *self, PyObject *args)
                 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;
 }
 
index ea34bcd9ded6b6ff50f288daa02d76e074306263..3c27fd6650249ff46832f7c7270704a97856ef35 100644 (file)
@@ -188,6 +188,7 @@ PyDoc_STRVAR(doc_a2b_uu, "(ascii) -> bin. Decode a line of uuencoded data");
 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 @@ binascii_a2b_uu(PyObject *self, PyObject *args)
        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 @@ binascii_a2b_uu(PyObject *self, PyObject *args)
        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 @@ binascii_a2b_uu(PyObject *self, PyObject *args)
                        return NULL;
                }
        }
+       PyBuffer_Release(&pascii);
        return rv;
 }
 
@@ -266,6 +272,7 @@ PyDoc_STRVAR(doc_b2a_uu, "(bin) -> ascii. Uuencode line of data");
 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 @@ binascii_b2a_uu(PyObject *self, PyObject *args)
        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 @@ binascii_b2a_uu(PyObject *self, PyObject *args)
                Py_DECREF(rv);
                rv = NULL;
        }
+       PyBuffer_Release(&pbin);
        return rv;
 }
 
@@ -346,6 +359,7 @@ PyDoc_STRVAR(doc_a2b_base64, "(ascii) -> bin. Decode a line of base64 data");
 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 @@ binascii_a2b_base64(PyObject *self, PyObject *args)
        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 @@ binascii_a2b_base64(PyObject *self, PyObject *args)
        }
 
        if (leftbits != 0) {
+               PyBuffer_Release(&pascii);
                PyErr_SetString(Error, "Incorrect padding");
                Py_DECREF(rv);
                return NULL;
@@ -438,6 +459,7 @@ binascii_a2b_base64(PyObject *self, PyObject *args)
                Py_DECREF(rv);
                rv = PyBytes_FromStringAndSize("", 0);
        }
+       PyBuffer_Release(&pascii);
        return rv;
 }
 
@@ -446,6 +468,7 @@ PyDoc_STRVAR(doc_b2a_base64, "(bin) -> ascii. Base64-code line of data");
 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 @@ binascii_b2a_base64(PyObject *self, PyObject *args)
        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 @@ binascii_b2a_base64(PyObject *self, PyObject *args)
                Py_DECREF(rv);
                rv = NULL;
        }
+       PyBuffer_Release(&pbuf);
        return rv;
 }
 
@@ -581,22 +610,29 @@ PyDoc_STRVAR(doc_rlecode_hqx, "Binhex RLE-code binary data");
 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 @@ binascii_rlecode_hqx(PyObject *self, PyObject *args)
                Py_DECREF(rv);
                rv = NULL;
        }
+       PyBuffer_Release(&pbuf);
        return rv;
 }
 
@@ -637,6 +674,7 @@ PyDoc_STRVAR(doc_b2a_hqx, "Encode .hqx data");
 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 @@ binascii_b2a_hqx(PyObject *self, PyObject *args)
        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 @@ binascii_b2a_hqx(PyObject *self, PyObject *args)
                Py_DECREF(rv);
                rv = NULL;
        }
+       PyBuffer_Release(&pbin);
        return rv;
 }
 
@@ -686,26 +731,35 @@ PyDoc_STRVAR(doc_rledecode_hqx, "Decode hexbin RLE-coded string");
 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 @@ binascii_rledecode_hqx(PyObject *self, PyObject *args)
                 if ( --in_len < 0 ) { \
                           PyErr_SetString(Incomplete, ""); \
                           Py_DECREF(rv); \
+                          PyBuffer_Release(&pin); \
                           return NULL; \
                 } \
                 b = *in_data++; \
@@ -728,7 +783,7 @@ binascii_rledecode_hqx(PyObject *self, PyObject *args)
                 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 @@ binascii_rledecode_hqx(PyObject *self, PyObject *args)
                Py_DECREF(rv);
                rv = NULL;
        }
+       PyBuffer_Release(&pin);
        return rv;
 }
 
@@ -792,17 +848,21 @@ PyDoc_STRVAR(doc_crc_hqx,
 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 @@ static PyObject *
 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 unsigned int crc_32_tab[256] = {
 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 @@ binascii_crc32(PyObject *self, PyObject *args)
        }
 
        result = (crc ^ 0xFFFFFFFF);
+       PyBuffer_Release(&pbuf);
        return PyLong_FromUnsignedLong(result & 0xffffffff);
 }
 #endif  /* USE_ZLIB_CRC32 */
@@ -969,22 +1037,29 @@ binascii_crc32(PyObject *self, PyObject *args)
 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 @@ binascii_hexlify(PyObject *self, PyObject *args)
                c = (c>9) ? c+'a'-10 : c + '0';
                retbuf[j++] = c;
        }
+       PyBuffer_Release(&parg);
        return retval;
 }
 
@@ -1024,14 +1100,17 @@ to_int(int c)
 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 @@ binascii_unhexlify(PyObject *self, PyObject *args)
         * 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 @@ binascii_unhexlify(PyObject *self, PyObject *args)
                }
                retbuf[j++] = (top << 4) + bot;
        }
+       PyBuffer_Release(&parg);
        return retval;
 
   finally:
+       PyBuffer_Release(&parg);
        Py_DECREF(retval);
        return NULL;
 }
@@ -1094,15 +1178,18 @@ binascii_a2b_qp(PyObject *self, PyObject *args, PyObject *kwargs)
 {
        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 @@ binascii_a2b_qp(PyObject *self, PyObject *args, PyObject *kwargs)
         */
        odata = (unsigned char *) PyMem_Malloc(datalen);
        if (odata == NULL) {
+               PyBuffer_Release(&pdata);
                PyErr_NoMemory();
                return NULL;
        }
@@ -1160,9 +1248,11 @@ binascii_a2b_qp(PyObject *self, PyObject *args, PyObject *kwargs)
                }
        }
        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 @@ static PyObject*
 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 @@ binascii_b2a_qp (PyObject *self, PyObject *args, PyObject *kwargs)
        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 @@ binascii_b2a_qp (PyObject *self, PyObject *args, PyObject *kwargs)
         */
        odata = (unsigned char *) PyMem_Malloc(odatalen);
        if (odata == NULL) {
+               PyBuffer_Release(&pdata);
                PyErr_NoMemory();
                return NULL;
        }
@@ -1360,9 +1454,11 @@ binascii_b2a_qp (PyObject *self, PyObject *args, PyObject *kwargs)
                }
        }
        if ((rv = PyBytes_FromStringAndSize((char *)odata, out)) == NULL) {
+               PyBuffer_Release(&pdata);
                PyMem_Free(odata);
                return NULL;
        }
+       PyBuffer_Release(&pdata);
        PyMem_Free(odata);
        return rv;
 }
index c6819914153dfe41cbdc767b1783958afe6d5590..4bf31ee2f920d0f82810881faa82c6dc50e4fd38 100644 (file)
@@ -691,12 +691,15 @@ static PyObject *
 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 @@ BZ2File_write(BZ2FileObject *self, PyObject *args)
        ret = Py_None;
 
 cleanup:
+       PyBuffer_Release(&pbuf);
        RELEASE_LOCK(self);
        return ret;
 }
@@ -1353,6 +1357,7 @@ and return what is left in the internal buffers.\n\
 static PyObject *
 BZ2Comp_compress(BZ2CompObject *self, PyObject *args)
 {
+       Py_buffer pdata;
        char *data;
        int datasize;
        int bufsize = SMALLCHUNK;
@@ -1361,11 +1366,15 @@ BZ2Comp_compress(BZ2CompObject *self, PyObject *args)
        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 @@ BZ2Comp_compress(BZ2CompObject *self, PyObject *args)
                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 @@ unused_data attribute.\n\
 static PyObject *
 BZ2Decomp_decompress(BZ2DecompObject *self, PyObject *args)
 {
+       Py_buffer pdata;
        char *data;
        int datasize;
        int bufsize = SMALLCHUNK;
@@ -1650,8 +1662,10 @@ BZ2Decomp_decompress(BZ2DecompObject *self, PyObject *args)
        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 @@ BZ2Decomp_decompress(BZ2DecompObject *self, PyObject *args)
        }
 
        RELEASE_LOCK(self);
+       PyBuffer_Release(&pdata);
        return ret;
 
 error:
        RELEASE_LOCK(self);
+       PyBuffer_Release(&pdata);
        Py_XDECREF(ret);
        return NULL;
 }
@@ -1853,6 +1869,7 @@ static PyObject *
 bz2_compress(PyObject *self, PyObject *args, PyObject *kwargs)
 {
        int compresslevel=9;
+       Py_buffer pdata;
        char *data;
        int datasize;
        int bufsize;
@@ -1862,14 +1879,17 @@ bz2_compress(PyObject *self, PyObject *args, PyObject *kwargs)
        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 @@ bz2_compress(PyObject *self, PyObject *args, PyObject *kwargs)
        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 @@ bz2_compress(PyObject *self, PyObject *args, PyObject *kwargs)
        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 @@ bz2_compress(PyObject *self, PyObject *args, PyObject *kwargs)
                } else if (bzerror != BZ_FINISH_OK) {
                        BZ2_bzCompressEnd(bzs);
                        Util_CatchBZ2Error(bzerror);
+                       PyBuffer_Release(&pdata);
                        Py_DECREF(ret);
                        return NULL;
                }
@@ -1911,6 +1935,7 @@ bz2_compress(PyObject *self, PyObject *args, PyObject *kwargs)
                        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_compress(PyObject *self, PyObject *args, PyObject *kwargs)
        }
        BZ2_bzCompressEnd(bzs);
 
+       PyBuffer_Release(&pdata);
        return ret;
 }
 
@@ -1938,6 +1964,7 @@ use an instance of BZ2Decompressor instead.\n\
 static PyObject *
 bz2_decompress(PyObject *self, PyObject *args)
 {
+       Py_buffer pdata;
        char *data;
        int datasize;
        int bufsize = SMALLCHUNK;
@@ -1946,15 +1973,21 @@ bz2_decompress(PyObject *self, PyObject *args)
        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 @@ bz2_decompress(PyObject *self, PyObject *args)
        if (bzerror != BZ_OK) {
                Util_CatchBZ2Error(bzerror);
                Py_DECREF(ret);
+               PyBuffer_Release(&pdata);
                return NULL;
        }
 
@@ -1979,6 +2013,7 @@ bz2_decompress(PyObject *self, PyObject *args)
                } else if (bzerror != BZ_OK) {
                        BZ2_bzDecompressEnd(bzs);
                        Util_CatchBZ2Error(bzerror);
+                       PyBuffer_Release(&pdata);
                        Py_DECREF(ret);
                        return NULL;
                }
@@ -1986,6 +2021,7 @@ bz2_decompress(PyObject *self, PyObject *args)
                        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 @@ bz2_decompress(PyObject *self, PyObject *args)
                        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_decompress(PyObject *self, PyObject *args)
                }
        }
        BZ2_bzDecompressEnd(bzs);
+       PyBuffer_Release(&pdata);
 
        return ret;
 }
index dbd5314e0a720dfa2803e20b91e0212cb36ad152..95b2278e6c608edfcfd80b0f15ce26be697598eb 100644 (file)
@@ -608,18 +608,24 @@ MultibyteCodec_Decode(MultibyteCodecObject *self,
        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 @@ MultibyteCodec_Decode(MultibyteCodecObject *self,
                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);
index 46bf4d117224ce5035cbfb8070f768d9749fae21..5331ea8c4d690ac8f4910292d55b6e2bdacbcf8c 100644 (file)
@@ -113,15 +113,18 @@ fcntl_ioctl(PyObject *self, PyObject *args)
        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 @@ fcntl_ioctl(PyObject *self, PyObject *args)
                }
                else {
                        if (len > IOCTL_BUFSZ) {
+                               PyBuffer_Release(&pstr);
                                PyErr_SetString(PyExc_ValueError,
                                        "ioctl string arg too long");
                                return NULL;
@@ -156,6 +160,7 @@ fcntl_ioctl(PyObject *self, PyObject *args)
                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 @@ fcntl_ioctl(PyObject *self, PyObject *args)
        }
 
        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 @@ fcntl_ioctl(PyObject *self, PyObject *args)
                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);
        }
 
index 51ad69c07058adfec43a64f459f4b60ea809f562..c8dfc24e0daf6883302070efff55ac5d7da0959a 100644 (file)
@@ -651,7 +651,7 @@ static int
 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 @@ mmap_ass_subscript(mmap_object *self, PyObject *item, PyObject *value)
                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 @@ mmap_ass_subscript(mmap_object *self, PyObject *item, PyObject *value)
                                self->data[cur] = ((char *)vbuf.buf)[i];
                        }
                }
-               PyObject_ReleaseBuffer(value, &vbuf);
+               PyBuffer_Release(&vbuf);
                return 0;
        }
        else {
index 3b79d05a610d74840b3241ed703680e297d67be8..b499b47817737a8608959843d1791cd892e0894d 100644 (file)
@@ -4894,15 +4894,16 @@ Write a string to a file descriptor.");
 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);
index de802ae1b0cdf9ca0454c9f4a54b2503e101f822..7d91af22da08ad0c24161b2aeba1a9a93ed79aa3 100644 (file)
@@ -2251,15 +2251,19 @@ sock_recv_into(PySocketSockObject *s, PyObject *args, PyObject *kwds)
 
        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 @@ sock_recv_into(PySocketSockObject *s, PyObject *args, PyObject *kwds)
 
        /* 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 @@ sock_recv_into(PySocketSockObject *s, PyObject *args, PyObject *kwds)
        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 @@ sock_recvfrom_into(PySocketSockObject *s, PyObject *args, PyObject* kwds)
 
        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 @@ sock_recvfrom_into(PySocketSockObject *s, PyObject *args, PyObject* kwds)
 
        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 @@ sock_send(PySocketSockObject *s, PyObject *args)
 {
        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 @@ sock_send(PySocketSockObject *s, PyObject *args)
 #endif
        Py_END_ALLOW_THREADS
 
+       PyBuffer_Release(&pbuf);
+
        if (timeout == 1) {
                PyErr_SetString(socket_timeout, "timed out");
                return NULL;
@@ -2511,12 +2531,17 @@ sock_sendall(PySocketSockObject *s, PyObject *args)
 {
        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 @@ sock_sendall(PySocketSockObject *s, PyObject *args)
                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 @@ to tell how much data has been sent.");
 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 @@ sock_sendto(PySocketSockObject *s, PyObject *args)
                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;
index b6f324bfcce33fd26d232dce69603b0afe8a9764..3fa84d91d87af9b63b34674ff2479e6ffee388dc 100644 (file)
@@ -118,18 +118,22 @@ static PyObject *
 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 @@ PyZlib_compress(PyObject *self, PyObject *args)
        zlib_error(zst, err, "while finishing compression");
 
  error:
+    PyBuffer_Release(&pinput);
     free(output);
 
     return ReturnVal;
@@ -195,15 +200,18 @@ static PyObject *
 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 @@ PyZlib_decompress(PyObject *self, PyObject *args)
     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 @@ PyZlib_decompress(PyObject *self, PyObject *args)
     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 @@ PyZlib_objcompress(compobject *self, PyObject *args)
 {
     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 @@ PyZlib_objcompress(compobject *self, PyObject *args)
 
  error:
     LEAVE_ZLIB
+    PyBuffer_Release(&pinput);
     return RetVal;
 }
 
@@ -472,13 +490,17 @@ PyZlib_objdecompress(compobject *self, PyObject *args)
     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 @@ PyZlib_objdecompress(compobject *self, PyObject *args)
     /* 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 @@ PyZlib_objdecompress(compobject *self, PyObject *args)
 
  error:
     LEAVE_ZLIB
-
+    PyBuffer_Release(&pinput);
     return RetVal;
 }
 
@@ -916,12 +940,13 @@ static PyObject *
 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);
 }
 
index f15883e668b48e83fce9b3a2ea03897e1b0f6a31..6b73acad10ce104779f2dacf1e46924a4f7ae1ec 100644 (file)
@@ -349,16 +349,6 @@ PyObject_GetBuffer(PyObject *obj, Py_buffer *view, int flags)
        return (*(obj->ob_type->tp_as_buffer->bf_getbuffer))(obj, view, flags);
 }
 
-void
-PyObject_ReleaseBuffer(PyObject *obj, Py_buffer *view)
-{
-       if (obj->ob_type->tp_as_buffer != NULL &&
-           obj->ob_type->tp_as_buffer->bf_releasebuffer != NULL) {
-               (*(obj->ob_type->tp_as_buffer->bf_releasebuffer))(obj, view);
-       }
-}
-
-
 static int
 _IsFortranContiguous(Py_buffer *view)
 {
@@ -590,15 +580,15 @@ int PyObject_CopyData(PyObject *dest, PyObject *src)
 
        if (PyObject_GetBuffer(dest, &view_dest, PyBUF_FULL) != 0) return -1;
        if (PyObject_GetBuffer(src, &view_src, PyBUF_FULL_RO) != 0) {
-               PyObject_ReleaseBuffer(dest, &view_dest);
+               PyBuffer_Release(&view_dest);
                return -1;
        }
 
        if (view_dest.len < view_src.len) {
                PyErr_SetString(PyExc_BufferError,
                                "destination is too small to receive data from source");
-               PyObject_ReleaseBuffer(dest, &view_dest);
-               PyObject_ReleaseBuffer(src, &view_src);
+               PyBuffer_Release(&view_dest);
+               PyBuffer_Release(&view_src);
                return -1;
        }
 
@@ -608,8 +598,8 @@ int PyObject_CopyData(PyObject *dest, PyObject *src)
             PyBuffer_IsContiguous(&view_src, 'F'))) {
                /* simplest copy is all that is needed */
                memcpy(view_dest.buf, view_src.buf, view_src.len);
-               PyObject_ReleaseBuffer(dest, &view_dest);
-               PyObject_ReleaseBuffer(src, &view_src);
+               PyBuffer_Release(&view_dest);
+               PyBuffer_Release(&view_src);
                return 0;
        }
 
@@ -619,8 +609,8 @@ int PyObject_CopyData(PyObject *dest, PyObject *src)
        indices = (Py_ssize_t *)PyMem_Malloc(sizeof(Py_ssize_t)*view_src.ndim);
        if (indices == NULL) {
                PyErr_NoMemory();
-               PyObject_ReleaseBuffer(dest, &view_dest);
-               PyObject_ReleaseBuffer(src, &view_src);
+               PyBuffer_Release(&view_dest);
+               PyBuffer_Release(&view_src);
                return -1;
        }
        for (k=0; k<view_src.ndim;k++) {
@@ -638,8 +628,8 @@ int PyObject_CopyData(PyObject *dest, PyObject *src)
                memcpy(dptr, sptr, view_src.itemsize);
        }
        PyMem_Free(indices);
-       PyObject_ReleaseBuffer(dest, &view_dest);
-       PyObject_ReleaseBuffer(src, &view_src);
+       PyBuffer_Release(&view_dest);
+       PyBuffer_Release(&view_src);
        return 0;
 }
 
@@ -668,7 +658,7 @@ PyBuffer_FillContiguousStrides(int nd, Py_ssize_t *shape,
 }
 
 int
-PyBuffer_FillInfo(Py_buffer *view, void *buf, Py_ssize_t len,
+PyBuffer_FillInfo(Py_buffer *view, PyObject *obj, void *buf, Py_ssize_t len,
              int readonly, int flags)
 {
        if (view == NULL) return 0;
@@ -679,6 +669,7 @@ PyBuffer_FillInfo(Py_buffer *view, void *buf, Py_ssize_t len,
                return -1;
        }
 
+       view->obj = obj;
        view->buf = buf;
        view->len = len;
        view->readonly = readonly;
@@ -698,6 +689,17 @@ PyBuffer_FillInfo(Py_buffer *view, void *buf, Py_ssize_t len,
        return 0;
 }
 
+void
+PyBuffer_Release(Py_buffer *view)
+{
+       PyObject *obj = view->obj;
+       if (!obj || !Py_TYPE(obj)->tp_as_buffer || !Py_TYPE(obj)->tp_as_buffer->bf_releasebuffer)
+               /* Unmanaged buffer */
+               return;
+       Py_TYPE(obj)->tp_as_buffer->bf_releasebuffer(obj, view);
+       
+}
+
 PyObject *
 PyObject_Format(PyObject *obj, PyObject *format_spec)
 {
index a76f8274d250f0ac92b44333b8b603729e165f69..dfe0a8600571b288ffda7aeabbce574316db997d 100644 (file)
@@ -69,7 +69,7 @@ bytes_getbuffer(PyByteArrayObject *obj, Py_buffer *view, int flags)
         ptr = "";
     else
         ptr = obj->ob_bytes;
-    ret = PyBuffer_FillInfo(view, ptr, Py_SIZE(obj), 0, flags);
+    ret = PyBuffer_FillInfo(view, (PyObject*)obj, ptr, Py_SIZE(obj), 0, flags);
     if (ret >= 0) {
         obj->ob_exports++;
     }
@@ -248,9 +248,9 @@ PyByteArray_Concat(PyObject *a, PyObject *b)
 
   done:
     if (va.len != -1)
-        PyObject_ReleaseBuffer(a, &va);
+        PyBuffer_Release(&va);
     if (vb.len != -1)
-        PyObject_ReleaseBuffer(b, &vb);
+        PyBuffer_Release(&vb);
     return (PyObject *)result;
 }
 
@@ -278,7 +278,7 @@ bytes_iconcat(PyByteArrayObject *self, PyObject *other)
     mysize = Py_SIZE(self);
     size = mysize + vo.len;
     if (size < 0) {
-        PyObject_ReleaseBuffer(other, &vo);
+        PyBuffer_Release(&vo);
         return PyErr_NoMemory();
     }
     if (size < self->ob_alloc) {
@@ -286,11 +286,11 @@ bytes_iconcat(PyByteArrayObject *self, PyObject *other)
         self->ob_bytes[Py_SIZE(self)] = '\0'; /* Trailing null byte */
     }
     else if (PyByteArray_Resize((PyObject *)self, size) < 0) {
-        PyObject_ReleaseBuffer(other, &vo);
+        PyBuffer_Release(&vo);
         return NULL;
     }
     memcpy(self->ob_bytes + mysize, vo.buf, vo.len);
-    PyObject_ReleaseBuffer(other, &vo);
+    PyBuffer_Release(&vo);
     Py_INCREF(self);
     return (PyObject *)self;
 }
@@ -501,7 +501,7 @@ bytes_setslice(PyByteArrayObject *self, Py_ssize_t lo, Py_ssize_t hi,
 
  finish:
     if (vbytes.len != -1)
-            PyObject_ReleaseBuffer(values, &vbytes);
+            PyBuffer_Release(&vbytes);
     return res;
 }
 
@@ -767,10 +767,10 @@ bytes_init(PyByteArrayObject *self, PyObject *args, PyObject *kwds)
         if (PyByteArray_Resize((PyObject *)self, size) < 0) goto fail;
         if (PyBuffer_ToContiguous(self->ob_bytes, &view, size, 'C') < 0)
                 goto fail;
-        PyObject_ReleaseBuffer(arg, &view);
+        PyBuffer_Release(&view);
         return 0;
     fail:
-        PyObject_ReleaseBuffer(arg, &view);
+        PyBuffer_Release(&view);
         return -1;
     }
 
@@ -954,7 +954,7 @@ bytes_richcompare(PyObject *self, PyObject *other, int op)
     other_size = _getbuffer(other, &other_bytes);
     if (other_size < 0) {
         PyErr_Clear();
-        PyObject_ReleaseBuffer(self, &self_bytes);
+        PyBuffer_Release(&self_bytes);
         Py_INCREF(Py_NotImplemented);
         return Py_NotImplemented;
     }
@@ -989,8 +989,8 @@ bytes_richcompare(PyObject *self, PyObject *other, int op)
     }
 
     res = cmp ? Py_True : Py_False;
-    PyObject_ReleaseBuffer(self, &self_bytes);
-    PyObject_ReleaseBuffer(other, &other_bytes);
+    PyBuffer_Release(&self_bytes);
+    PyBuffer_Release(&other_bytes);
     Py_INCREF(res);
     return res;
 }
@@ -998,6 +998,11 @@ bytes_richcompare(PyObject *self, PyObject *other, int op)
 static void
 bytes_dealloc(PyByteArrayObject *self)
 {
+       if (self->ob_exports > 0) {
+               PyErr_SetString(PyExc_SystemError,
+                       "deallocated bytearray object has exported buffers");
+               PyErr_Print();
+       }
     if (self->ob_bytes != 0) {
         PyMem_Free(self->ob_bytes);
     }
@@ -1065,7 +1070,7 @@ bytes_find_internal(PyByteArrayObject *self, PyObject *args, int dir)
         res = stringlib_rfind_slice(
             PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self),
             subbuf.buf, subbuf.len, start, end);
-    PyObject_ReleaseBuffer(subobj, &subbuf);
+    PyBuffer_Release(&subbuf);
     return res;
 }
 
@@ -1115,7 +1120,7 @@ bytes_count(PyByteArrayObject *self, PyObject *args)
     count_obj = PyLong_FromSsize_t(
         stringlib_count(str + start, end - start, vsub.buf, vsub.len)
         );
-    PyObject_ReleaseBuffer(sub_obj, &vsub);
+    PyBuffer_Release(&vsub);
     return count_obj;
 }
 
@@ -1191,7 +1196,7 @@ bytes_contains(PyObject *self, PyObject *arg)
             return -1;
         pos = stringlib_find(PyByteArray_AS_STRING(self), Py_SIZE(self),
                              varg.buf, varg.len, 0);
-        PyObject_ReleaseBuffer(arg, &varg);
+        PyBuffer_Release(&varg);
         return pos >= 0;
     }
     if (ival < 0 || ival >= 256) {
@@ -1241,7 +1246,7 @@ _bytes_tailmatch(PyByteArrayObject *self, PyObject *substr, Py_ssize_t start,
         rv = ! memcmp(str+start, vsubstr.buf, vsubstr.len);
 
 done:
-    PyObject_ReleaseBuffer(substr, &vsubstr);
+    PyBuffer_Release(&vsubstr);
     return rv;
 }
 
@@ -1421,9 +1426,9 @@ bytes_translate(PyByteArrayObject *self, PyObject *args)
         PyByteArray_Resize(result, output - output_start);
 
 done:
-    PyObject_ReleaseBuffer(tableobj, &vtable);
+    PyBuffer_Release(&vtable);
     if (delobj != NULL)
-        PyObject_ReleaseBuffer(delobj, &vdel);
+        PyBuffer_Release(&vdel);
     return result;
 }
 
@@ -2042,7 +2047,7 @@ bytes_replace(PyByteArrayObject *self, PyObject *args)
     if (_getbuffer(from, &vfrom) < 0)
         return NULL;
     if (_getbuffer(to, &vto) < 0) {
-        PyObject_ReleaseBuffer(from, &vfrom);
+        PyBuffer_Release(&vfrom);
         return NULL;
     }
 
@@ -2050,8 +2055,8 @@ bytes_replace(PyByteArrayObject *self, PyObject *args)
                               vfrom.buf, vfrom.len,
                               vto.buf, vto.len, count);
 
-    PyObject_ReleaseBuffer(from, &vfrom);
-    PyObject_ReleaseBuffer(to, &vto);
+    PyBuffer_Release(&vfrom);
+    PyBuffer_Release(&vto);
     return res;
 }
 
@@ -2207,7 +2212,7 @@ bytes_split(PyByteArrayObject *self, PyObject *args)
 
     if (n == 0) {
         PyErr_SetString(PyExc_ValueError, "empty separator");
-        PyObject_ReleaseBuffer(subobj, &vsub);
+        PyBuffer_Release(&vsub);
         return NULL;
     }
     if (n == 1)
@@ -2215,7 +2220,7 @@ bytes_split(PyByteArrayObject *self, PyObject *args)
 
     list = PyList_New(PREALLOC_SIZE(maxsplit));
     if (list == NULL) {
-        PyObject_ReleaseBuffer(subobj, &vsub);
+        PyBuffer_Release(&vsub);
         return NULL;
     }
 
@@ -2243,12 +2248,12 @@ bytes_split(PyByteArrayObject *self, PyObject *args)
 #endif
     SPLIT_ADD(s, i, len);
     FIX_PREALLOC_SIZE(list);
-    PyObject_ReleaseBuffer(subobj, &vsub);
+    PyBuffer_Release(&vsub);
     return list;
 
   onError:
     Py_DECREF(list);
-    PyObject_ReleaseBuffer(subobj, &vsub);
+    PyBuffer_Release(&vsub);
     return NULL;
 }
 
@@ -2439,7 +2444,7 @@ bytes_rsplit(PyByteArrayObject *self, PyObject *args)
 
     if (n == 0) {
         PyErr_SetString(PyExc_ValueError, "empty separator");
-        PyObject_ReleaseBuffer(subobj, &vsub);
+        PyBuffer_Release(&vsub);
         return NULL;
     }
     else if (n == 1)
@@ -2447,7 +2452,7 @@ bytes_rsplit(PyByteArrayObject *self, PyObject *args)
 
     list = PyList_New(PREALLOC_SIZE(maxsplit));
     if (list == NULL) {
-        PyObject_ReleaseBuffer(subobj, &vsub);
+        PyBuffer_Release(&vsub);
         return NULL;
     }
 
@@ -2468,12 +2473,12 @@ bytes_rsplit(PyByteArrayObject *self, PyObject *args)
     FIX_PREALLOC_SIZE(list);
     if (PyList_Reverse(list) < 0)
         goto onError;
-    PyObject_ReleaseBuffer(subobj, &vsub);
+    PyBuffer_Release(&vsub);
     return list;
 
 onError:
     Py_DECREF(list);
-    PyObject_ReleaseBuffer(subobj, &vsub);
+    PyBuffer_Release(&vsub);
     return NULL;
 }
 
@@ -2749,7 +2754,7 @@ bytes_strip(PyByteArrayObject *self, PyObject *args)
     else
         right = rstrip_helper(myptr, mysize, argptr, argsize);
     if (arg != Py_None)
-        PyObject_ReleaseBuffer(arg, &varg);
+        PyBuffer_Release(&varg);
     return PyByteArray_FromStringAndSize(self->ob_bytes + left, right - left);
 }
 
@@ -2783,7 +2788,7 @@ bytes_lstrip(PyByteArrayObject *self, PyObject *args)
     left = lstrip_helper(myptr, mysize, argptr, argsize);
     right = mysize;
     if (arg != Py_None)
-        PyObject_ReleaseBuffer(arg, &varg);
+        PyBuffer_Release(&varg);
     return PyByteArray_FromStringAndSize(self->ob_bytes + left, right - left);
 }
 
@@ -2817,7 +2822,7 @@ bytes_rstrip(PyByteArrayObject *self, PyObject *args)
     left = 0;
     right = rstrip_helper(myptr, mysize, argptr, argsize);
     if (arg != Py_None)
-        PyObject_ReleaseBuffer(arg, &varg);
+        PyBuffer_Release(&varg);
     return PyByteArray_FromStringAndSize(self->ob_bytes + left, right - left);
 }
 
index 7c1469c1a9e706356ebd5afd93e25958d91a05c0..52479ca41d749196c12ca93fa54c8518c0565e44 100644 (file)
@@ -710,9 +710,9 @@ string_concat(PyObject *a, PyObject *b)
 
   done:
        if (va.len != -1)
-               PyObject_ReleaseBuffer(a, &va);
+               PyBuffer_Release(&va);
        if (vb.len != -1)
-               PyObject_ReleaseBuffer(b, &vb);
+               PyBuffer_Release(&vb);
        return result;
 }
 
@@ -781,7 +781,7 @@ string_contains(PyObject *self, PyObject *arg)
             return -1;
         pos = stringlib_find(PyBytes_AS_STRING(self), Py_SIZE(self),
                              varg.buf, varg.len, 0);
-        PyObject_ReleaseBuffer(arg, &varg);
+        PyBuffer_Release(&varg);
         return pos >= 0;
     }
     if (ival < 0 || ival >= 256) {
@@ -964,7 +964,7 @@ string_subscript(PyBytesObject* self, PyObject* item)
 static int
 string_buffer_getbuffer(PyBytesObject *self, Py_buffer *view, int flags)
 {
-       return PyBuffer_FillInfo(view, (void *)self->ob_sval, Py_SIZE(self),
+       return PyBuffer_FillInfo(view, (PyObject*)self, (void *)self->ob_sval, Py_SIZE(self),
                                 1, flags);
 }
 
@@ -1160,7 +1160,7 @@ string_split(PyBytesObject *self, PyObject *args)
 
        if (n == 0) {
                PyErr_SetString(PyExc_ValueError, "empty separator");
-               PyObject_ReleaseBuffer(subobj, &vsub);
+               PyBuffer_Release(&vsub);
                return NULL;
        }
        else if (n == 1)
@@ -1168,7 +1168,7 @@ string_split(PyBytesObject *self, PyObject *args)
 
        list = PyList_New(PREALLOC_SIZE(maxsplit));
        if (list == NULL) {
-               PyObject_ReleaseBuffer(subobj, &vsub);
+               PyBuffer_Release(&vsub);
                return NULL;
        }
 
@@ -1196,12 +1196,12 @@ string_split(PyBytesObject *self, PyObject *args)
 #endif
        SPLIT_ADD(s, i, len);
        FIX_PREALLOC_SIZE(list);
-       PyObject_ReleaseBuffer(subobj, &vsub);
+       PyBuffer_Release(&vsub);
        return list;
 
  onError:
        Py_DECREF(list);
-       PyObject_ReleaseBuffer(subobj, &vsub);
+       PyBuffer_Release(&vsub);
        return NULL;
 }
 
@@ -1376,7 +1376,7 @@ string_rsplit(PyBytesObject *self, PyObject *args)
 
        if (n == 0) {
                PyErr_SetString(PyExc_ValueError, "empty separator");
-               PyObject_ReleaseBuffer(subobj, &vsub);
+               PyBuffer_Release(&vsub);
                return NULL;
        }
        else if (n == 1)
@@ -1384,7 +1384,7 @@ string_rsplit(PyBytesObject *self, PyObject *args)
 
        list = PyList_New(PREALLOC_SIZE(maxsplit));
        if (list == NULL) {
-               PyObject_ReleaseBuffer(subobj, &vsub);
+               PyBuffer_Release(&vsub);
                return NULL;
        }
 
@@ -1406,12 +1406,12 @@ string_rsplit(PyBytesObject *self, PyObject *args)
        FIX_PREALLOC_SIZE(list);
        if (PyList_Reverse(list) < 0)
                goto onError;
-       PyObject_ReleaseBuffer(subobj, &vsub);
+       PyBuffer_Release(&vsub);
        return list;
 
 onError:
        Py_DECREF(list);
-       PyObject_ReleaseBuffer(subobj, &vsub);
+       PyBuffer_Release(&vsub);
        return NULL;
 }
 
@@ -1690,7 +1690,7 @@ do_xstrip(PyBytesObject *self, int striptype, PyObject *sepobj)
                j++;
        }
 
-       PyObject_ReleaseBuffer(sepobj, &vsep);
+       PyBuffer_Release(&vsep);
 
        if (i == 0 && j == len && PyBytes_CheckExact(self)) {
                Py_INCREF(self);
@@ -2945,11 +2945,11 @@ string_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
                if (PyBuffer_ToContiguous(((PyBytesObject *)new)->ob_sval,
                                          &view, view.len, 'C') < 0)
                        goto fail;
-               PyObject_ReleaseBuffer(x, &view);
+               PyBuffer_Release(&view);
                return new;
          fail:
                Py_XDECREF(new);
-               PyObject_ReleaseBuffer(x, &view);
+               PyBuffer_Release(&view);
                return NULL;
        }
 
index 79d7db1b0221b5df9fa5b2797967afe384abb6a0..b36c3a7ade599c2ae383ef3b71adfd036de5807e 100644 (file)
@@ -6,19 +6,21 @@
 static int
 memory_getbuf(PyMemoryViewObject *self, Py_buffer *view, int flags)
 {
-        if (view != NULL)
+        if (view != NULL) {
+               if (self->view.obj)
+                       Py_INCREF(self->view.obj);
                *view = self->view;
-       if (self->base == NULL)
+       }
+       if (self->view.obj == NULL)
                return 0;
-        return self->base->ob_type->tp_as_buffer->bf_getbuffer(self->base, NULL,
+        return self->view.obj->ob_type->tp_as_buffer->bf_getbuffer(self->base, NULL,
                                                                PyBUF_FULL);
 }
 
 static void
 memory_releasebuf(PyMemoryViewObject *self, Py_buffer *view)
 {
-       if (self->base != NULL)
-               PyObject_ReleaseBuffer(self->base, NULL);
+       PyBuffer_Release(&self->view);
 }
 
 PyDoc_STRVAR(memory_doc,
@@ -36,6 +38,8 @@ PyMemoryView_FromMemory(Py_buffer *info)
        if (mview == NULL) return NULL;
        mview->base = NULL;
        mview->view = *info;
+       if (info->obj)
+               Py_INCREF(mview->view.obj);
        return (PyObject *)mview;
 }
 
@@ -256,7 +260,7 @@ PyMemoryView_GetContiguous(PyObject *obj, int buffertype, char fort)
         }
         bytes = PyByteArray_FromStringAndSize(NULL, view->len);
         if (bytes == NULL) {
-                PyObject_ReleaseBuffer(obj, view);
+                PyBuffer_Release(view);
                 return NULL;
         }
         dest = PyByteArray_AS_STRING(bytes);
@@ -271,7 +275,7 @@ PyMemoryView_GetContiguous(PyObject *obj, int buffertype, char fort)
         else {
                 if (_indirect_copy_nd(dest, view, fort) < 0) {
                         Py_DECREF(bytes);
-                        PyObject_ReleaseBuffer(obj, view);
+                        PyBuffer_Release(view);
                         return NULL;
                 }
         }
@@ -281,12 +285,12 @@ PyMemoryView_GetContiguous(PyObject *obj, int buffertype, char fort)
                 mem->base = PyTuple_Pack(2, obj, bytes);
                 Py_DECREF(bytes);
                if (mem->base == NULL) {
-                       PyObject_ReleaseBuffer(obj, view);
+                       PyBuffer_Release(view);
                        return NULL;
                }
         }
         else {
-                PyObject_ReleaseBuffer(obj, view);
+                PyBuffer_Release(view);
                 /* steal the reference */
                 mem->base = bytes;
         }
@@ -407,7 +411,7 @@ static PyMethodDef memory_methods[] = {
 static void
 memory_dealloc(PyMemoryViewObject *self)
 {
-        if (self->base != NULL) {
+        if (self->view.obj != NULL) {
             if (PyTuple_Check(self->base)) {
                 /* Special case when first element is generic object
                    with buffer interface and the second element is a
@@ -424,11 +428,10 @@ memory_dealloc(PyMemoryViewObject *self)
                    be "locked" and was locked and will be unlocked
                    again after this call.
                 */
-                PyObject_ReleaseBuffer(PyTuple_GET_ITEM(self->base,0),
-                                       &(self->view));
+                PyBuffer_Release(&(self->view));
             }
             else {
-                PyObject_ReleaseBuffer(self->base, &(self->view));
+                PyBuffer_Release(&(self->view));
             }
             Py_CLEAR(self->base);
         }
@@ -453,7 +456,7 @@ memory_str(PyMemoryViewObject *self)
 
        res = PyByteArray_FromStringAndSize(NULL, view.len);
         PyBuffer_ToContiguous(PyByteArray_AS_STRING(res), &view, view.len, 'C');
-        PyObject_ReleaseBuffer((PyObject *)self, &view);
+        PyBuffer_Release(&view);
         return res;
 }
 
@@ -466,7 +469,7 @@ memory_length(PyMemoryViewObject *self)
 
         if (PyObject_GetBuffer((PyObject *)self, &view, PyBUF_FULL) < 0)
                 return -1;
-        PyObject_ReleaseBuffer((PyObject *)self, &view);
+        PyBuffer_Release(&view);
        return view.len;
 }
 
index 897e390a3ad120e870fa180de15cf26980998afa..5de265d74df90f598787e26df971500704520953 100644 (file)
@@ -1198,7 +1198,7 @@ PyObject *PyUnicode_Decode(const char *s,
 
     /* Decode via the codec registry */
     buffer = NULL;
-    if (PyBuffer_FillInfo(&info, (void *)s, size, 1, PyBUF_SIMPLE) < 0)
+    if (PyBuffer_FillInfo(&info, NULL, (void *)s, size, 1, PyBUF_SIMPLE) < 0)
         goto onError;
     buffer = PyMemoryView_FromMemory(&info);
     if (buffer == NULL)
index e53a448e1d497fab7dc377bad8fa2f962ca8fe93..1536e1735f4ab8d01b62ed88b7d230e25fd976ba 100644 (file)
@@ -814,13 +814,13 @@ Py2Reg(PyObject *value, DWORD typ, BYTE **retDataBuf, DWORD *retDataSize)
 
                                *retDataBuf = (BYTE *)PyMem_NEW(char, view.len);
                                if (*retDataBuf==NULL){
-                                       PyObject_ReleaseBuffer(value, &view);
+                                       PyBuffer_Release(&view);
                                        PyErr_NoMemory();
                                        return FALSE;
                                }
                                *retDataSize = view.len;
                                memcpy(*retDataBuf, view.buf, view.len);
-                               PyObject_ReleaseBuffer(value, &view);
+                               PyBuffer_Release(&view);
                        }
                        break;
        }
index 36a6261cc3e509033755d04a84dc5ef4ef5812e9..cf4444c36e70a198311ff1d2eb9b62b0712ac3a5 100644 (file)
@@ -44,6 +44,7 @@ static char *converttuple(PyObject *, const char **, va_list *, int,
 static char *convertsimple(PyObject *, const char **, va_list *, int, char *,
                           size_t, PyObject **);
 static Py_ssize_t convertbuffer(PyObject *, void **p, char **);
+static int getbuffer(PyObject *, Py_buffer *, char**);
 
 static int vgetargskeywords(PyObject *, PyObject *,
                            const char *, char **, va_list *, int);
@@ -789,7 +790,25 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags,
           need to be cleaned up! */
 
        case 's': {/* text string */
-               if (*format == '#') {
+               if (*format == '*') {
+                       Py_buffer *p = (Py_buffer *)va_arg(*p_va, Py_buffer *);
+
+                       if (PyUnicode_Check(arg)) {
+                               uarg = UNICODE_DEFAULT_ENCODING(arg);
+                               if (uarg == NULL)
+                                       return converterr(CONV_UNICODE,
+                                                         arg, msgbuf, bufsize);
+                               PyBuffer_FillInfo(p, arg,
+                                                 PyBytes_AS_STRING(uarg), PyBytes_GET_SIZE(uarg),
+                                                 1, 0);
+                       }
+                       else { /* any buffer-like object */
+                               char *buf;
+                               if (getbuffer(arg, p, &buf) < 0)
+                                       return converterr(buf, arg, msgbuf, bufsize);
+                       }
+                       format++;
+               } else if (*format == '#') {
                        void **p = (void **)va_arg(*p_va, char **);
                        FETCH_SIZE;
 
@@ -832,10 +851,17 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags,
        case 'y': {/* any buffer-like object, but not PyUnicode */
                void **p = (void **)va_arg(*p_va, char **);
                char *buf;
-               Py_ssize_t count = convertbuffer(arg, p, &buf);
+               Py_ssize_t count;
+               if (*format == '*') {
+                       if (getbuffer(arg, (Py_buffer*)p, &buf) < 0)
+                               return converterr(buf, arg, msgbuf, bufsize);
+                       format++;
+                       break;
+               }
+               count = convertbuffer(arg, p, &buf);
                if (count < 0)
                        return converterr(buf, arg, msgbuf, bufsize);
-               if (*format == '#') {
+               else if (*format == '#') {
                        FETCH_SIZE;
                        STORE_SIZE(count);
                        format++;
@@ -844,7 +870,27 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags,
        }
 
        case 'z': {/* like 's' or 's#', but None is okay, stored as NULL */
-               if (*format == '#') { /* any buffer-like object */
+               if (*format == '*') {
+                       Py_buffer *p = (Py_buffer *)va_arg(*p_va, Py_buffer *);
+
+                       if (arg == Py_None)
+                               PyBuffer_FillInfo(p, NULL, NULL, 0, 1, 0);
+                       else if (PyUnicode_Check(arg)) {
+                               uarg = UNICODE_DEFAULT_ENCODING(arg);
+                               if (uarg == NULL)
+                                       return converterr(CONV_UNICODE,
+                                                         arg, msgbuf, bufsize);
+                               PyBuffer_FillInfo(p, arg,
+                                                 PyBytes_AS_STRING(uarg), PyBytes_GET_SIZE(uarg),
+                                                 1, 0);
+                       }
+                       else { /* any buffer-like object */
+                               char *buf;
+                               if (getbuffer(arg, p, &buf) < 0)
+                                       return converterr(buf, arg, msgbuf, bufsize);
+                       }
+                       format++;
+               } else if (*format == '#') { /* any buffer-like object */
                        void **p = (void **)va_arg(*p_va, char **);
                        FETCH_SIZE;
 
@@ -1189,6 +1235,26 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags,
                 int temp=-1;
                 Py_buffer view;
 
+               if (pb && pb->bf_releasebuffer && *format != '*')
+                       /* Buffer must be released, yet caller does not use
+                          the Py_buffer protocol. */
+                       return converterr("pinned buffer", arg, msgbuf, bufsize);
+
+
+               if (pb && pb->bf_getbuffer && *format == '*') {
+                       /* Caller is interested in Py_buffer, and the object
+                          supports it directly. */
+                       format++;
+                       if (pb->bf_getbuffer(arg, (Py_buffer*)p, PyBUF_WRITABLE) < 0) {
+                               PyErr_Clear();
+                               return converterr("read-write buffer", arg, msgbuf, bufsize);
+                       }
+                       if (!PyBuffer_IsContiguous((Py_buffer*)p, 'C'))
+                               return converterr("contiguous buffer", arg, msgbuf, bufsize);
+                       break;
+               }
+
+               /* Here we have processed w*, only w and w# remain. */
                if (pb == NULL ||
                    pb->bf_getbuffer == NULL ||
                     ((temp = (*pb->bf_getbuffer)(arg, &view,
@@ -1209,8 +1275,6 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags,
                        STORE_SIZE(count);
                        format++;
                }
-                if (pb->bf_releasebuffer != NULL)
-                        (*pb->bf_releasebuffer)(arg, &view);
                break;
        }
 
@@ -1237,10 +1301,11 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags,
 
                 count = view.len;
                 *p = view.buf;
-                /* XXX : shouldn't really release buffer, but it should be O.K.
-                */
-                if (pb->bf_releasebuffer != NULL)
-                        (*pb->bf_releasebuffer)(arg, &view);
+               if (pb->bf_releasebuffer)
+                       return converterr(
+                               "string or pinned buffer",
+                               arg, msgbuf, bufsize);
+
                if (count < 0)
                        return converterr("(unspecified)", arg, msgbuf, bufsize);
                {
@@ -1269,7 +1334,8 @@ convertbuffer(PyObject *arg, void **p, char **errmsg)
         *errmsg = NULL;
         *p = NULL;
        if (pb == NULL ||
-           pb->bf_getbuffer == NULL) {
+           pb->bf_getbuffer == NULL ||
+           pb->bf_releasebuffer != NULL) {
                *errmsg = "bytes or read-only buffer";
                return -1;
        }
@@ -1285,6 +1351,35 @@ convertbuffer(PyObject *arg, void **p, char **errmsg)
        return count;
 }
 
+/* XXX for 3.x, getbuffer and convertbuffer can probably
+   be merged again. */
+static int
+getbuffer(PyObject *arg, Py_buffer *view, char**errmsg)
+{
+       void *buf;
+       Py_ssize_t count;
+       PyBufferProcs *pb = arg->ob_type->tp_as_buffer;
+       if (pb == NULL) {
+               *errmsg = "string or buffer";
+               return -1;
+       }
+       if (pb->bf_getbuffer) {
+               if (pb->bf_getbuffer(arg, view, 0) < 0)
+                       return -1;
+               if (!PyBuffer_IsContiguous(view, 'C')) {
+                       *errmsg = "contiguous buffer";
+                       return -1;
+               }
+               return 0;
+       }
+
+       count = convertbuffer(arg, &buf, errmsg);
+       if (count < 0)
+               return count;
+       PyBuffer_FillInfo(view, NULL, buf, count, 1, 0);
+       return 0;
+}
+
 /* Support for keyword arguments donated by
    Geoff Philbrick <philbric@delphi.hks.com> */
 
@@ -1624,6 +1719,8 @@ skipitem(const char **p_format, va_list *p_va, int flags)
                                else
                                        (void) va_arg(*p_va, int *);
                                format++;
+                       } else if ((c == 's' || c == 'z' || c == 'y') && *format == '*') {
+                               format++;
                        }
                        break;
                }
index e7e4154fbd2011952e5abfda6c72671c3426aa18..d3f2d7f48f19c6ea2c6c20820c16c21b2d28858f 100644 (file)
@@ -1168,11 +1168,14 @@ static PyObject *
 marshal_loads(PyObject *self, PyObject *args)
 {
        RFILE rf;
+       Py_buffer p;
        char *s;
        Py_ssize_t n;
        PyObject* result;
-       if (!PyArg_ParseTuple(args, "s#:loads", &s, &n))
+       if (!PyArg_ParseTuple(args, "s*:loads", &p))
                return NULL;
+       s = p.buf;
+       n = p.len;
        rf.fp = NULL;
        rf.ptr = s;
        rf.end = s + n;
@@ -1180,6 +1183,7 @@ marshal_loads(PyObject *self, PyObject *args)
        rf.depth = 0;
        result = read_object(&rf);
        Py_DECREF(rf.strings);
+       PyBuffer_Release(&p);
        return result;
 }