From 423be95dcf55b0b8737207beb7b30eb549430dba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20v=2E=20L=C3=B6wis?= Date: Wed, 13 Aug 2008 15:53:07 +0000 Subject: Merged revisions 65654 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r65654 | martin.v.loewis | 2008-08-12 16:49:50 +0200 (Tue, 12 Aug 2008) | 6 lines Issue #3139: Make buffer-interface thread-safe wrt. PyArg_ParseTuple, by denying s# to parse objects that have a releasebuffer procedure, and introducing s*. More module might need to get converted to use s*. ........ --- Doc/c-api/arg.rst | 15 ++ Doc/whatsnew/2.6.rst | 4 +- Include/abstract.h | 24 +-- Include/object.h | 3 +- Lib/test/test_sys.py | 2 +- Modules/_bsddb.c | 4 +- Modules/_codecsmodule.c | 279 ++++++++++++++++------------------ Modules/_ctypes/_ctypes.c | 6 +- Modules/_fileio.c | 15 +- Modules/_hashopenssl.c | 14 +- Modules/_json.c | 2 +- Modules/_multiprocessing/connection.h | 36 +++-- Modules/_sre.c | 2 +- Modules/_struct.c | 8 +- Modules/arraymodule.c | 2 + Modules/audioop.c | 9 +- Modules/binascii.c | 160 +++++++++++++++---- Modules/bz2module.c | 58 +++++-- Modules/cjkcodecs/multibytecodec.c | 14 +- Modules/fcntlmodule.c | 18 ++- Modules/mmapmodule.c | 6 +- Modules/posixmodule.c | 7 +- Modules/socketmodule.c | 63 ++++++-- Modules/zlibmodule.c | 53 +++++-- Objects/abstract.c | 42 ++--- Objects/bytearrayobject.c | 69 +++++---- Objects/bytesobject.c | 30 ++-- Objects/memoryobject.c | 33 ++-- Objects/unicodeobject.c | 2 +- PC/winreg.c | 4 +- Python/getargs.c | 119 +++++++++++++-- Python/marshal.c | 6 +- 32 files changed, 720 insertions(+), 389 deletions(-) diff --git a/Doc/c-api/arg.rst b/Doc/c-api/arg.rst index faf97ed..de7b930 100644 --- a/Doc/c-api/arg.rst +++ b/Doc/c-api/arg.rst @@ -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 diff --git a/Doc/whatsnew/2.6.rst b/Doc/whatsnew/2.6.rst index c0ecf01..0f8b883 100644 --- a/Doc/whatsnew/2.6.rst +++ b/Doc/whatsnew/2.6.rst @@ -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 diff --git a/Include/abstract.h b/Include/abstract.h index 9a1003b..46a6f54 100644 --- a/Include/abstract.h +++ b/Include/abstract.h @@ -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); diff --git a/Include/object.h b/Include/object.h index f5ec7d4..372eada 100644 --- a/Include/object.h +++ b/Include/object.h @@ -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.*/ diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py index f3c72e7..04288d9 100644 --- a/Lib/test/test_sys.py +++ b/Lib/test/test_sys.py @@ -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 diff --git a/Modules/_bsddb.c b/Modules/_bsddb.c index 648fb0d..7c0eae3 100644 --- a/Modules/_bsddb.c +++ b/Modules/_bsddb.c @@ -288,7 +288,7 @@ static void free_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; } diff --git a/Modules/_codecsmodule.c b/Modules/_codecsmodule.c index 96dfd56..5026c05 100644 --- a/Modules/_codecsmodule.c +++ b/Modules/_codecsmodule.c @@ -252,20 +252,20 @@ 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 * diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c index 02a08a4..7ef3ea1 100644 --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -1050,10 +1050,10 @@ 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 */ diff --git a/Modules/_fileio.c b/Modules/_fileio.c index f520f0c..f0c8fed 100644 --- a/Modules/_fileio.c +++ b/Modules/_fileio.c @@ -357,7 +357,7 @@ 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; diff --git a/Modules/_hashopenssl.c b/Modules/_hashopenssl.c index bd04411..c0f9a2c 100644 --- a/Modules/_hashopenssl.c +++ b/Modules/_hashopenssl.c @@ -164,7 +164,7 @@ 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; \ } diff --git a/Modules/_json.c b/Modules/_json.c index 1cf1e63..a724f89 100644 --- a/Modules/_json.c +++ b/Modules/_json.c @@ -261,7 +261,7 @@ 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); diff --git a/Modules/_multiprocessing/connection.h b/Modules/_multiprocessing/connection.h index d651a97..e422d69 100644 --- a/Modules/_multiprocessing/connection.h +++ b/Modules/_multiprocessing/connection.h @@ -96,21 +96,26 @@ 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; } /* diff --git a/Modules/_sre.c b/Modules/_sre.c index 4511c1b..64fc513 100644 --- a/Modules/_sre.c +++ b/Modules/_sre.c @@ -1704,7 +1704,7 @@ 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"); diff --git a/Modules/_struct.c b/Modules/_struct.c index 43be9ed..4a257c0 100644 --- a/Modules/_struct.c +++ b/Modules/_struct.c @@ -1567,11 +1567,11 @@ 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; } diff --git a/Modules/arraymodule.c b/Modules/arraymodule.c index b5f819e..16a7a7e 100644 --- a/Modules/arraymodule.c +++ b/Modules/arraymodule.c @@ -1820,6 +1820,8 @@ 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; diff --git a/Modules/audioop.c b/Modules/audioop.c index c54e512..b2fdb9a 100644 --- a/Modules/audioop.c +++ b/Modules/audioop.c @@ -783,20 +783,24 @@ 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; } diff --git a/Modules/binascii.c b/Modules/binascii.c index ea34bcd..3c27fd6 100644 --- a/Modules/binascii.c +++ b/Modules/binascii.c @@ -188,6 +188,7 @@ 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= 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, "etabs, &istext, &header)) + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s*|iii", kwlist, &pdata, + "etabs, &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; } diff --git a/Modules/bz2module.c b/Modules/bz2module.c index c681991..4bf31ee 100644 --- a/Modules/bz2module.c +++ b/Modules/bz2module.c @@ -691,12 +691,15 @@ 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; } diff --git a/Modules/cjkcodecs/multibytecodec.c b/Modules/cjkcodecs/multibytecodec.c index dbd5314..95b2278 100644 --- a/Modules/cjkcodecs/multibytecodec.c +++ b/Modules/cjkcodecs/multibytecodec.c @@ -608,18 +608,24 @@ MultibyteCodec_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); diff --git a/Modules/fcntlmodule.c b/Modules/fcntlmodule.c index 46bf4d1..5331ea8 100644 --- a/Modules/fcntlmodule.c +++ b/Modules/fcntlmodule.c @@ -113,15 +113,18 @@ 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); } diff --git a/Modules/mmapmodule.c b/Modules/mmapmodule.c index 51ad69c..c8dfc24 100644 --- a/Modules/mmapmodule.c +++ b/Modules/mmapmodule.c @@ -651,7 +651,7 @@ 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 { diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index 3b79d05..b499b47 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -4894,15 +4894,16 @@ 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); diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c index de802ae..7d91af2 100644 --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -2251,15 +2251,19 @@ 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; diff --git a/Modules/zlibmodule.c b/Modules/zlibmodule.c index b6f324b..3fa84d9 100644 --- a/Modules/zlibmodule.c +++ b/Modules/zlibmodule.c @@ -118,18 +118,22 @@ 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); } diff --git a/Objects/abstract.c b/Objects/abstract.c index f15883e..6b73aca 100644 --- a/Objects/abstract.c +++ b/Objects/abstract.c @@ -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; kobj = 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) { diff --git a/Objects/bytearrayobject.c b/Objects/bytearrayobject.c index a76f827..dfe0a86 100644 --- a/Objects/bytearrayobject.c +++ b/Objects/bytearrayobject.c @@ -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); } diff --git a/Objects/bytesobject.c b/Objects/bytesobject.c index 7c1469c..52479ca 100644 --- a/Objects/bytesobject.c +++ b/Objects/bytesobject.c @@ -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; } diff --git a/Objects/memoryobject.c b/Objects/memoryobject.c index 79d7db1..b36c3a7 100644 --- a/Objects/memoryobject.c +++ b/Objects/memoryobject.c @@ -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; } diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c index 897e390..5de265d 100644 --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -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) diff --git a/PC/winreg.c b/PC/winreg.c index e53a448..1536e17 100644 --- a/PC/winreg.c +++ b/PC/winreg.c @@ -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; } diff --git a/Python/getargs.c b/Python/getargs.c index 36a6261..cf4444c 100644 --- a/Python/getargs.c +++ b/Python/getargs.c @@ -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 */ @@ -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; } diff --git a/Python/marshal.c b/Python/marshal.c index e7e4154..d3f2d7f 100644 --- a/Python/marshal.c +++ b/Python/marshal.c @@ -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; } -- cgit v0.12