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*.
........
This commit is contained in:
Martin v. Löwis 2008-08-13 15:53:07 +00:00
parent 688356f59f
commit 423be95dcf
32 changed files with 721 additions and 390 deletions

View 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 other read-buffer compatible objects pass back a reference to the raw internal
data representation. 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 \*] ``y`` (bytes object) [const char \*]
This variant on ``s`` convert a Python bytes object to a C pointer to a 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 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 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. 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 \*] ``z`` (string or ``None``) [const char \*]
Like ``s``, but the Python object may also be ``None``, in which case the C Like ``s``, but the Python object may also be ``None``, in which case the C
pointer is set to *NULL*. 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] ``z#`` (string or ``None`` or any read buffer compatible object) [const char \*, int]
This is to ``s#`` as ``z`` is to ``s``. 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 \*] ``u`` (Unicode object) [Py_UNICODE \*]
Convert a Python Unicode object to a C pointer to a NUL-terminated buffer of 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 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 single-segment buffer objects are accepted; :exc:`TypeError` is raised for all
others. others.
``w*`` (read-write byte-oriented buffer) [Py_buffer \*]
This is to ``w`` what ``s*`` is to ``s``.
``(items)`` (tuple) [*matching-items*] ``(items)`` (tuple) [*matching-items*]
The object must be a Python sequence whose length is the number of format units 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 in *items*. The C arguments must correspond to the individual format units in

View file

@ -1064,7 +1064,7 @@ about the object's memory representation. Objects
can use this operation to lock memory in place can use this operation to lock memory in place
while an external caller could be modifying the contents, while an external caller could be modifying the contents,
so there's a corresponding 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. indicate that the external caller is done.
The **flags** argument to :cfunc:`PyObject_GetBuffer` specifies 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 new buffer interface, previously described in
`the PEP 3118 section <#pep-3118-revised-buffer-protocol>`__, `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. as well as a few other functions.
* Python's use of the C stdio library is now thread-safe, or at least * Python's use of the C stdio library is now thread-safe, or at least

View 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); 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. /* Get the memory area pointed to by the indices for the buffer given.
@ -600,7 +582,7 @@ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/
per element. 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, Py_ssize_t len, int readonly,
int flags); int flags);
@ -610,6 +592,10 @@ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/
and -1 (with raising an error) on error. 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, PyAPI_FUNC(PyObject *) PyObject_Format(PyObject* obj,
PyObject *format_spec); PyObject *format_spec);

View file

@ -143,6 +143,7 @@ typedef int(*objobjargproc)(PyObject *, PyObject *, PyObject *);
/* buffer interface */ /* buffer interface */
typedef struct bufferinfo { typedef struct bufferinfo {
void *buf; void *buf;
PyObject *obj; /* borrowed reference */
Py_ssize_t len; Py_ssize_t len;
Py_ssize_t itemsize; /* This is Py_ssize_t so it can be Py_ssize_t itemsize; /* This is Py_ssize_t so it can be
pointed to by strides in simple case.*/ pointed to by strides in simple case.*/

View file

@ -550,7 +550,7 @@ class SizeofTest(unittest.TestCase):
check(32768*32768-1, size(vh) + 2*self.H) check(32768*32768-1, size(vh) + 2*self.H)
check(32768*32768, size(vh) + 3*self.H) check(32768*32768, size(vh) + 3*self.H)
# memory # memory
check(memoryview(b''), size(h + 'P P2P2i5P')) check(memoryview(b''), size(h + 'P PP2P2i5P'))
# module # module
check(unittest, size(h + '3P')) check(unittest, size(h + '3P'))
# None # None

View file

@ -288,7 +288,7 @@ static void free_dbt(DBT *dbt)
static void free_buf_view(PyObject *obj, Py_buffer *view) static void free_buf_view(PyObject *obj, Py_buffer *view)
{ {
if (view) { if (view) {
PyObject_ReleaseBuffer(obj, view); PyBuffer_Release(view);
PyMem_Free(view); PyMem_Free(view);
} }
} }
@ -319,7 +319,7 @@ static Py_buffer * _malloc_view(PyObject *obj)
if (view->ndim > 1) { if (view->ndim > 1) {
PyErr_SetString(PyExc_BufferError, PyErr_SetString(PyExc_BufferError,
"buffers must be single dimension"); "buffers must be single dimension");
PyObject_ReleaseBuffer(obj, view); PyBuffer_Release(view);
PyMem_Free(view); PyMem_Free(view);
return NULL; return NULL;
} }

View file

@ -252,20 +252,20 @@ static PyObject *
utf_7_decode(PyObject *self, utf_7_decode(PyObject *self,
PyObject *args) PyObject *args)
{ {
const char *data; Py_buffer pbuf;
Py_ssize_t size;
const char *errors = NULL; const char *errors = NULL;
int final = 0; int final = 0;
Py_ssize_t consumed; Py_ssize_t consumed;
PyObject *decoded = NULL; PyObject *decoded = NULL;
if (!PyArg_ParseTuple(args, "t#|zi:utf_7_decode", if (!PyArg_ParseTuple(args, "s*|zi:utf_7_decode",
&data, &size, &errors, &final)) &pbuf, &errors, &final))
return NULL; return NULL;
consumed = size; consumed = pbuf.len;
decoded = PyUnicode_DecodeUTF7Stateful(data, size, errors, decoded = PyUnicode_DecodeUTF7Stateful(pbuf.buf, pbuf.len, errors,
final ? NULL : &consumed); final ? NULL : &consumed);
PyBuffer_Release(&pbuf);
if (decoded == NULL) if (decoded == NULL)
return NULL; return NULL;
return codec_tuple(decoded, consumed); return codec_tuple(decoded, consumed);
@ -275,24 +275,20 @@ static PyObject *
utf_8_decode(PyObject *self, utf_8_decode(PyObject *self,
PyObject *args) PyObject *args)
{ {
const char *data; Py_buffer pbuf;
Py_ssize_t size;
const char *errors = NULL; const char *errors = NULL;
int final = 0; int final = 0;
Py_ssize_t consumed; Py_ssize_t consumed;
PyObject *decoded = NULL; PyObject *decoded = NULL;
if (!PyArg_ParseTuple(args, "t#|zi:utf_8_decode", if (!PyArg_ParseTuple(args, "s*|zi:utf_8_decode",
&data, &size, &errors, &final)) &pbuf, &errors, &final))
return NULL; return NULL;
if (size < 0) { consumed = pbuf.len;
PyErr_SetString(PyExc_ValueError, "negative argument");
return 0;
}
consumed = size;
decoded = PyUnicode_DecodeUTF8Stateful(data, size, errors, decoded = PyUnicode_DecodeUTF8Stateful(pbuf.buf, pbuf.len, errors,
final ? NULL : &consumed); final ? NULL : &consumed);
PyBuffer_Release(&pbuf);
if (decoded == NULL) if (decoded == NULL)
return NULL; return NULL;
return codec_tuple(decoded, consumed); return codec_tuple(decoded, consumed);
@ -302,24 +298,20 @@ static PyObject *
utf_16_decode(PyObject *self, utf_16_decode(PyObject *self,
PyObject *args) PyObject *args)
{ {
const char *data; Py_buffer pbuf;
Py_ssize_t size;
const char *errors = NULL; const char *errors = NULL;
int byteorder = 0; int byteorder = 0;
int final = 0; int final = 0;
Py_ssize_t consumed; Py_ssize_t consumed;
PyObject *decoded; PyObject *decoded;
if (!PyArg_ParseTuple(args, "t#|zi:utf_16_decode", if (!PyArg_ParseTuple(args, "s*|zi:utf_16_decode",
&data, &size, &errors, &final)) &pbuf, &errors, &final))
return NULL; return NULL;
if (size < 0) { consumed = pbuf.len; /* This is overwritten unless final is true. */
PyErr_SetString(PyExc_ValueError, "negative argument"); decoded = PyUnicode_DecodeUTF16Stateful(pbuf.buf, pbuf.len, errors,
return 0; &byteorder, final ? NULL : &consumed);
} PyBuffer_Release(&pbuf);
consumed = size; /* This is overwritten unless final is true. */
decoded = PyUnicode_DecodeUTF16Stateful(data, size, errors, &byteorder,
final ? NULL : &consumed);
if (decoded == NULL) if (decoded == NULL)
return NULL; return NULL;
return codec_tuple(decoded, consumed); return codec_tuple(decoded, consumed);
@ -329,53 +321,45 @@ static PyObject *
utf_16_le_decode(PyObject *self, utf_16_le_decode(PyObject *self,
PyObject *args) PyObject *args)
{ {
const char *data; Py_buffer pbuf;
Py_ssize_t size;
const char *errors = NULL; const char *errors = NULL;
int byteorder = -1; int byteorder = -1;
int final = 0; int final = 0;
Py_ssize_t consumed; Py_ssize_t consumed;
PyObject *decoded = NULL; PyObject *decoded = NULL;
if (!PyArg_ParseTuple(args, "t#|zi:utf_16_le_decode", if (!PyArg_ParseTuple(args, "s*|zi:utf_16_le_decode",
&data, &size, &errors, &final)) &pbuf, &errors, &final))
return NULL; return NULL;
if (size < 0) { consumed = pbuf.len; /* This is overwritten unless final is true. */
PyErr_SetString(PyExc_ValueError, "negative argument"); decoded = PyUnicode_DecodeUTF16Stateful(pbuf.buf, pbuf.len, errors,
return 0;
}
consumed = size; /* This is overwritten unless final is true. */
decoded = PyUnicode_DecodeUTF16Stateful(data, size, errors,
&byteorder, final ? NULL : &consumed); &byteorder, final ? NULL : &consumed);
PyBuffer_Release(&pbuf);
if (decoded == NULL) if (decoded == NULL)
return NULL; return NULL;
return codec_tuple(decoded, consumed); return codec_tuple(decoded, consumed);
} }
static PyObject * static PyObject *
utf_16_be_decode(PyObject *self, utf_16_be_decode(PyObject *self,
PyObject *args) PyObject *args)
{ {
const char *data; Py_buffer pbuf;
Py_ssize_t size;
const char *errors = NULL; const char *errors = NULL;
int byteorder = 1; int byteorder = 1;
int final = 0; int final = 0;
Py_ssize_t consumed; Py_ssize_t consumed;
PyObject *decoded = NULL; PyObject *decoded = NULL;
if (!PyArg_ParseTuple(args, "t#|zi:utf_16_be_decode", if (!PyArg_ParseTuple(args, "s*|zi:utf_16_be_decode",
&data, &size, &errors, &final)) &pbuf, &errors, &final))
return NULL; return NULL;
if (size < 0) {
PyErr_SetString(PyExc_ValueError, "negative argument"); consumed = pbuf.len; /* This is overwritten unless final is true. */
return 0; decoded = PyUnicode_DecodeUTF16Stateful(pbuf.buf, pbuf.len, errors,
}
consumed = size; /* This is overwritten unless final is true. */
decoded = PyUnicode_DecodeUTF16Stateful(data, size, errors,
&byteorder, final ? NULL : &consumed); &byteorder, final ? NULL : &consumed);
PyBuffer_Release(&pbuf);
if (decoded == NULL) if (decoded == NULL)
return NULL; return NULL;
return codec_tuple(decoded, consumed); return codec_tuple(decoded, consumed);
@ -393,24 +377,20 @@ static PyObject *
utf_16_ex_decode(PyObject *self, utf_16_ex_decode(PyObject *self,
PyObject *args) PyObject *args)
{ {
const char *data; Py_buffer pbuf;
Py_ssize_t size;
const char *errors = NULL; const char *errors = NULL;
int byteorder = 0; int byteorder = 0;
PyObject *unicode, *tuple; PyObject *unicode, *tuple;
int final = 0; int final = 0;
Py_ssize_t consumed; Py_ssize_t consumed;
if (!PyArg_ParseTuple(args, "t#|zii:utf_16_ex_decode", if (!PyArg_ParseTuple(args, "s*|zii:utf_16_ex_decode",
&data, &size, &errors, &byteorder, &final)) &pbuf, &errors, &byteorder, &final))
return NULL; return NULL;
if (size < 0) { consumed = pbuf.len; /* This is overwritten unless final is true. */
PyErr_SetString(PyExc_ValueError, "negative argument"); unicode = PyUnicode_DecodeUTF16Stateful(pbuf.buf, pbuf.len, errors,
return 0; &byteorder, final ? NULL : &consumed);
} PyBuffer_Release(&pbuf);
consumed = size; /* This is overwritten unless final is true. */
unicode = PyUnicode_DecodeUTF16Stateful(data, size, errors, &byteorder,
final ? NULL : &consumed);
if (unicode == NULL) if (unicode == NULL)
return NULL; return NULL;
tuple = Py_BuildValue("Oni", unicode, consumed, byteorder); tuple = Py_BuildValue("Oni", unicode, consumed, byteorder);
@ -422,24 +402,20 @@ static PyObject *
utf_32_decode(PyObject *self, utf_32_decode(PyObject *self,
PyObject *args) PyObject *args)
{ {
const char *data; Py_buffer pbuf;
Py_ssize_t size;
const char *errors = NULL; const char *errors = NULL;
int byteorder = 0; int byteorder = 0;
int final = 0; int final = 0;
Py_ssize_t consumed; Py_ssize_t consumed;
PyObject *decoded; PyObject *decoded;
if (!PyArg_ParseTuple(args, "t#|zi:utf_32_decode", if (!PyArg_ParseTuple(args, "s*|zi:utf_32_decode",
&data, &size, &errors, &final)) &pbuf, &errors, &final))
return NULL; return NULL;
if (size < 0) { consumed = pbuf.len; /* This is overwritten unless final is true. */
PyErr_SetString(PyExc_ValueError, "negative argument"); decoded = PyUnicode_DecodeUTF32Stateful(pbuf.buf, pbuf.len, errors,
return 0; &byteorder, final ? NULL : &consumed);
} PyBuffer_Release(&pbuf);
consumed = size; /* This is overwritten unless final is true. */
decoded = PyUnicode_DecodeUTF32Stateful(data, size, errors, &byteorder,
final ? NULL : &consumed);
if (decoded == NULL) if (decoded == NULL)
return NULL; return NULL;
return codec_tuple(decoded, consumed); return codec_tuple(decoded, consumed);
@ -449,53 +425,43 @@ static PyObject *
utf_32_le_decode(PyObject *self, utf_32_le_decode(PyObject *self,
PyObject *args) PyObject *args)
{ {
const char *data; Py_buffer pbuf;
Py_ssize_t size;
const char *errors = NULL; const char *errors = NULL;
int byteorder = -1; int byteorder = -1;
int final = 0; int final = 0;
Py_ssize_t consumed; Py_ssize_t consumed;
PyObject *decoded = NULL; PyObject *decoded;
if (!PyArg_ParseTuple(args, "t#|zi:utf_32_le_decode", if (!PyArg_ParseTuple(args, "s*|zi:utf_32_le_decode",
&data, &size, &errors, &final)) &pbuf, &errors, &final))
return NULL; return NULL;
consumed = pbuf.len; /* This is overwritten unless final is true. */
if (size < 0) { decoded = PyUnicode_DecodeUTF32Stateful(pbuf.buf, pbuf.len, errors,
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); &byteorder, final ? NULL : &consumed);
PyBuffer_Release(&pbuf);
if (decoded == NULL) if (decoded == NULL)
return NULL; return NULL;
return codec_tuple(decoded, consumed); return codec_tuple(decoded, consumed);
} }
static PyObject * static PyObject *
utf_32_be_decode(PyObject *self, utf_32_be_decode(PyObject *self,
PyObject *args) PyObject *args)
{ {
const char *data; Py_buffer pbuf;
Py_ssize_t size;
const char *errors = NULL; const char *errors = NULL;
int byteorder = 1; int byteorder = 1;
int final = 0; int final = 0;
Py_ssize_t consumed; Py_ssize_t consumed;
PyObject *decoded = NULL; PyObject *decoded;
if (!PyArg_ParseTuple(args, "t#|zi:utf_32_be_decode", if (!PyArg_ParseTuple(args, "s*|zi:utf_32_be_decode",
&data, &size, &errors, &final)) &pbuf, &errors, &final))
return NULL; return NULL;
if (size < 0) { consumed = pbuf.len; /* This is overwritten unless final is true. */
PyErr_SetString(PyExc_ValueError, "negative argument"); decoded = PyUnicode_DecodeUTF32Stateful(pbuf.buf, pbuf.len, errors,
return 0;
}
consumed = size; /* This is overwritten unless final is true. */
decoded = PyUnicode_DecodeUTF32Stateful(data, size, errors,
&byteorder, final ? NULL : &consumed); &byteorder, final ? NULL : &consumed);
PyBuffer_Release(&pbuf);
if (decoded == NULL) if (decoded == NULL)
return NULL; return NULL;
return codec_tuple(decoded, consumed); return codec_tuple(decoded, consumed);
@ -513,24 +479,20 @@ static PyObject *
utf_32_ex_decode(PyObject *self, utf_32_ex_decode(PyObject *self,
PyObject *args) PyObject *args)
{ {
const char *data; Py_buffer pbuf;
Py_ssize_t size;
const char *errors = NULL; const char *errors = NULL;
int byteorder = 0; int byteorder = 0;
PyObject *unicode, *tuple; PyObject *unicode, *tuple;
int final = 0; int final = 0;
Py_ssize_t consumed; Py_ssize_t consumed;
if (!PyArg_ParseTuple(args, "t#|zii:utf_32_ex_decode", if (!PyArg_ParseTuple(args, "s*|zii:utf_32_ex_decode",
&data, &size, &errors, &byteorder, &final)) &pbuf, &errors, &byteorder, &final))
return NULL; return NULL;
if (size < 0) { consumed = pbuf.len; /* This is overwritten unless final is true. */
PyErr_SetString(PyExc_ValueError, "negative argument"); unicode = PyUnicode_DecodeUTF32Stateful(pbuf.buf, pbuf.len, errors,
return 0; &byteorder, final ? NULL : &consumed);
} PyBuffer_Release(&pbuf);
consumed = size; /* This is overwritten unless final is true. */
unicode = PyUnicode_DecodeUTF32Stateful(data, size, errors, &byteorder,
final ? NULL : &consumed);
if (unicode == NULL) if (unicode == NULL)
return NULL; return NULL;
tuple = Py_BuildValue("Oni", unicode, consumed, byteorder); tuple = Py_BuildValue("Oni", unicode, consumed, byteorder);
@ -542,83 +504,88 @@ static PyObject *
unicode_escape_decode(PyObject *self, unicode_escape_decode(PyObject *self,
PyObject *args) PyObject *args)
{ {
const char *data; Py_buffer pbuf;
Py_ssize_t size;
const char *errors = NULL; const char *errors = NULL;
PyObject *unicode;
if (!PyArg_ParseTuple(args, "t#|z:unicode_escape_decode", if (!PyArg_ParseTuple(args, "s*|z:unicode_escape_decode",
&data, &size, &errors)) &pbuf, &errors))
return NULL; return NULL;
return codec_tuple(PyUnicode_DecodeUnicodeEscape(data, size, errors), unicode = PyUnicode_DecodeUnicodeEscape(pbuf.buf, pbuf.len, errors);
size); PyBuffer_Release(&pbuf);
return codec_tuple(unicode, pbuf.len);
} }
static PyObject * static PyObject *
raw_unicode_escape_decode(PyObject *self, raw_unicode_escape_decode(PyObject *self,
PyObject *args) PyObject *args)
{ {
const char *data; Py_buffer pbuf;
Py_ssize_t size;
const char *errors = NULL; const char *errors = NULL;
PyObject *unicode;
if (!PyArg_ParseTuple(args, "t#|z:raw_unicode_escape_decode", if (!PyArg_ParseTuple(args, "s*|z:raw_unicode_escape_decode",
&data, &size, &errors)) &pbuf, &errors))
return NULL; return NULL;
return codec_tuple(PyUnicode_DecodeRawUnicodeEscape(data, size, errors), unicode = PyUnicode_DecodeRawUnicodeEscape(pbuf.buf, pbuf.len, errors);
size); PyBuffer_Release(&pbuf);
return codec_tuple(unicode, pbuf.len);
} }
static PyObject * static PyObject *
latin_1_decode(PyObject *self, latin_1_decode(PyObject *self,
PyObject *args) PyObject *args)
{ {
const char *data; Py_buffer pbuf;
Py_ssize_t size; PyObject *unicode;
const char *errors = NULL; const char *errors = NULL;
if (!PyArg_ParseTuple(args, "t#|z:latin_1_decode", if (!PyArg_ParseTuple(args, "s*|z:latin_1_decode",
&data, &size, &errors)) &pbuf, &errors))
return NULL; return NULL;
return codec_tuple(PyUnicode_DecodeLatin1(data, size, errors), unicode = PyUnicode_DecodeLatin1(pbuf.buf, pbuf.len, errors);
size); PyBuffer_Release(&pbuf);
return codec_tuple(unicode, pbuf.len);
} }
static PyObject * static PyObject *
ascii_decode(PyObject *self, ascii_decode(PyObject *self,
PyObject *args) PyObject *args)
{ {
const char *data; Py_buffer pbuf;
Py_ssize_t size; PyObject *unicode;
const char *errors = NULL; const char *errors = NULL;
if (!PyArg_ParseTuple(args, "t#|z:ascii_decode", if (!PyArg_ParseTuple(args, "s*|z:ascii_decode",
&data, &size, &errors)) &pbuf, &errors))
return NULL; return NULL;
return codec_tuple(PyUnicode_DecodeASCII(data, size, errors), unicode = PyUnicode_DecodeASCII(pbuf.buf, pbuf.len, errors);
size); PyBuffer_Release(&pbuf);
return codec_tuple(unicode, pbuf.len);
} }
static PyObject * static PyObject *
charmap_decode(PyObject *self, charmap_decode(PyObject *self,
PyObject *args) PyObject *args)
{ {
const char *data; Py_buffer pbuf;
Py_ssize_t size; PyObject *unicode;
const char *errors = NULL; const char *errors = NULL;
PyObject *mapping = NULL; PyObject *mapping = NULL;
if (!PyArg_ParseTuple(args, "t#|zO:charmap_decode", if (!PyArg_ParseTuple(args, "s*|zO:charmap_decode",
&data, &size, &errors, &mapping)) &pbuf, &errors, &mapping))
return NULL; return NULL;
if (mapping == Py_None) if (mapping == Py_None)
mapping = NULL; mapping = NULL;
return codec_tuple(PyUnicode_DecodeCharmap(data, size, mapping, errors), unicode = PyUnicode_DecodeCharmap(pbuf.buf, pbuf.len, mapping, errors);
size); PyBuffer_Release(&pbuf);
return codec_tuple(unicode, pbuf.len);
} }
#if defined(MS_WINDOWS) && defined(HAVE_USABLE_WCHAR_T) #if defined(MS_WINDOWS) && defined(HAVE_USABLE_WCHAR_T)
@ -627,21 +594,23 @@ static PyObject *
mbcs_decode(PyObject *self, mbcs_decode(PyObject *self,
PyObject *args) PyObject *args)
{ {
const char *data; Py_buffer pbuf;
Py_ssize_t size, consumed;
const char *errors = NULL; const char *errors = NULL;
int final = 0; int final = 0;
PyObject *decoded; Py_ssize_t consumed;
PyObject *decoded = NULL;
if (!PyArg_ParseTuple(args, "t#|zi:mbcs_decode", if (!PyArg_ParseTuple(args, "s*|zi:mbcs_decode",
&data, &size, &errors, &final)) &pbuf, &errors, &final))
return NULL; return NULL;
consumed = pbuf.len;
decoded = PyUnicode_DecodeMBCSStateful( decoded = PyUnicode_DecodeMBCSStateful(pbuf.buf, pbuf.len, errors,
data, size, errors, final ? NULL : &consumed); final ? NULL : &consumed);
if (!decoded) PyBuffer_Release(&pbuf);
if (decoded == NULL)
return NULL; return NULL;
return codec_tuple(decoded, final ? size : consumed); return codec_tuple(decoded, consumed);
} }
#endif /* MS_WINDOWS */ #endif /* MS_WINDOWS */
@ -652,15 +621,21 @@ static PyObject *
readbuffer_encode(PyObject *self, readbuffer_encode(PyObject *self,
PyObject *args) PyObject *args)
{ {
Py_buffer pdata;
const char *data; const char *data;
Py_ssize_t size; Py_ssize_t size;
const char *errors = NULL; const char *errors = NULL;
PyObject *result;
if (!PyArg_ParseTuple(args, "s#|z:readbuffer_encode", if (!PyArg_ParseTuple(args, "s*|z:readbuffer_encode",
&data, &size, &errors)) &pdata, &errors))
return NULL; 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 * static PyObject *

View file

@ -1050,10 +1050,10 @@ CharArray_set_raw(CDataObject *self, PyObject *value)
memcpy(self->b_ptr, ptr, size); memcpy(self->b_ptr, ptr, size);
PyObject_ReleaseBuffer(value, &view); PyBuffer_Release(&view);
return 0; return 0;
fail: fail:
PyObject_ReleaseBuffer(value, &view); PyBuffer_Release(&view);
return -1; return -1;
} }
@ -2462,6 +2462,8 @@ static int CData_GetBuffer(PyObject *_self, Py_buffer *view, int flags)
if (view == NULL) return 0; if (view == NULL) return 0;
view->buf = self->b_ptr; view->buf = self->b_ptr;
view->obj = _self;
Py_INCREF(_self);
view->len = self->b_size; view->len = self->b_size;
view->readonly = 0; view->readonly = 0;
/* use default format character if not set */ /* use default format character if not set */

View file

@ -357,7 +357,7 @@ fileio_seekable(PyFileIOObject *self)
static PyObject * static PyObject *
fileio_readinto(PyFileIOObject *self, PyObject *args) fileio_readinto(PyFileIOObject *self, PyObject *args)
{ {
char *ptr; Py_buffer pbuf;
Py_ssize_t n; Py_ssize_t n;
if (self->fd < 0) if (self->fd < 0)
@ -365,13 +365,14 @@ fileio_readinto(PyFileIOObject *self, PyObject *args)
if (!self->readable) if (!self->readable)
return err_mode("reading"); return err_mode("reading");
if (!PyArg_ParseTuple(args, "w#", &ptr, &n)) if (!PyArg_ParseTuple(args, "w*", &pbuf))
return NULL; return NULL;
Py_BEGIN_ALLOW_THREADS Py_BEGIN_ALLOW_THREADS
errno = 0; errno = 0;
n = read(self->fd, ptr, n); n = read(self->fd, pbuf.buf, pbuf.len);
Py_END_ALLOW_THREADS Py_END_ALLOW_THREADS
PyBuffer_Release(&pbuf);
if (n < 0) { if (n < 0) {
if (errno == EAGAIN) if (errno == EAGAIN)
Py_RETURN_NONE; Py_RETURN_NONE;
@ -489,22 +490,24 @@ fileio_read(PyFileIOObject *self, PyObject *args)
static PyObject * static PyObject *
fileio_write(PyFileIOObject *self, PyObject *args) fileio_write(PyFileIOObject *self, PyObject *args)
{ {
Py_buffer pbuf;
Py_ssize_t n; Py_ssize_t n;
char *ptr;
if (self->fd < 0) if (self->fd < 0)
return err_closed(); return err_closed();
if (!self->writable) if (!self->writable)
return err_mode("writing"); return err_mode("writing");
if (!PyArg_ParseTuple(args, "s#", &ptr, &n)) if (!PyArg_ParseTuple(args, "s*", &pbuf))
return NULL; return NULL;
Py_BEGIN_ALLOW_THREADS Py_BEGIN_ALLOW_THREADS
errno = 0; errno = 0;
n = write(self->fd, ptr, n); n = write(self->fd, pbuf.buf, pbuf.len);
Py_END_ALLOW_THREADS Py_END_ALLOW_THREADS
PyBuffer_Release(&pbuf);
if (n < 0) { if (n < 0) {
if (errno == EAGAIN) if (errno == EAGAIN)
Py_RETURN_NONE; Py_RETURN_NONE;

View file

@ -164,7 +164,7 @@ EVP_hexdigest(EVPobject *self, PyObject *unused)
if ((viewp)->ndim > 1) { \ if ((viewp)->ndim > 1) { \
PyErr_SetString(PyExc_BufferError, \ PyErr_SetString(PyExc_BufferError, \
"Buffer must be single dimension"); \ "Buffer must be single dimension"); \
PyObject_ReleaseBuffer((obj), (viewp)); \ PyBuffer_Release((viewp)); \
return NULL; \ return NULL; \
} \ } \
} while(0); } while(0);
@ -186,7 +186,7 @@ EVP_update(EVPobject *self, PyObject *args)
EVP_DigestUpdate(&self->ctx, (unsigned char*)view.buf, EVP_DigestUpdate(&self->ctx, (unsigned char*)view.buf,
Py_SAFE_DOWNCAST(view.len, Py_ssize_t, unsigned int)); Py_SAFE_DOWNCAST(view.len, Py_ssize_t, unsigned int));
PyObject_ReleaseBuffer(obj, &view); PyBuffer_Release(&view);
Py_INCREF(Py_None); Py_INCREF(Py_None);
return 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)) { if (!PyArg_Parse(name_obj, "s", &nameStr)) {
PyErr_SetString(PyExc_TypeError, "name must be a string"); PyErr_SetString(PyExc_TypeError, "name must be a string");
if (data_obj) if (data_obj)
PyObject_ReleaseBuffer(data_obj, &view); PyBuffer_Release(&view);
return -1; return -1;
} }
@ -275,7 +275,7 @@ EVP_tp_init(EVPobject *self, PyObject *args, PyObject *kwds)
if (!digest) { if (!digest) {
PyErr_SetString(PyExc_ValueError, "unknown hash function"); PyErr_SetString(PyExc_ValueError, "unknown hash function");
if (data_obj) if (data_obj)
PyObject_ReleaseBuffer(data_obj, &view); PyBuffer_Release(&view);
return -1; return -1;
} }
EVP_DigestInit(&self->ctx, digest); EVP_DigestInit(&self->ctx, digest);
@ -286,7 +286,7 @@ EVP_tp_init(EVPobject *self, PyObject *args, PyObject *kwds)
if (data_obj) { if (data_obj) {
EVP_DigestUpdate(&self->ctx, (unsigned char*)view.buf, EVP_DigestUpdate(&self->ctx, (unsigned char*)view.buf,
Py_SAFE_DOWNCAST(view.len, Py_ssize_t, unsigned int)); Py_SAFE_DOWNCAST(view.len, Py_ssize_t, unsigned int));
PyObject_ReleaseBuffer(data_obj, &view); PyBuffer_Release(&view);
} }
return 0; return 0;
@ -421,7 +421,7 @@ EVP_new(PyObject *self, PyObject *args, PyObject *kwdict)
Py_SAFE_DOWNCAST(view.len, Py_ssize_t, unsigned int)); Py_SAFE_DOWNCAST(view.len, Py_ssize_t, unsigned int));
if (data_obj) if (data_obj)
PyObject_ReleaseBuffer(data_obj, &view); PyBuffer_Release(&view);
return ret_obj; 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)); \ Py_SAFE_DOWNCAST(view.len, Py_ssize_t, unsigned int)); \
\ \
if (data_obj) \ if (data_obj) \
PyObject_ReleaseBuffer(data_obj, &view); \ PyBuffer_Release(&view); \
return ret_obj; \ return ret_obj; \
} }

View 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 */ /* Pick up this chunk if it's not zero length */
if (next != end) { if (next != end) {
PyObject *strchunk; 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; goto bail;
} }
strchunk = PyMemoryView_FromMemory(&info); strchunk = PyMemoryView_FromMemory(&info);

View file

@ -96,21 +96,26 @@ connection_dealloc(ConnectionObject* self)
static PyObject * static PyObject *
connection_sendbytes(ConnectionObject *self, PyObject *args) connection_sendbytes(ConnectionObject *self, PyObject *args)
{ {
Py_buffer pbuffer;
char *buffer; char *buffer;
Py_ssize_t length, offset=0, size=PY_SSIZE_T_MIN; Py_ssize_t length, offset=0, size=PY_SSIZE_T_MIN;
int res; int res;
if (!PyArg_ParseTuple(args, F_RBUFFER "#|" F_PY_SSIZE_T F_PY_SSIZE_T, if (!PyArg_ParseTuple(args, F_RBUFFER "*|" F_PY_SSIZE_T F_PY_SSIZE_T,
&buffer, &length, &offset, &size)) &pbuffer, &offset, &size))
return NULL; return NULL;
buffer = pbuffer.buf;
length = pbuffer.len;
CHECK_WRITABLE(self); CHECK_WRITABLE(self); /* XXX release buffer in case of failure */
if (offset < 0) { if (offset < 0) {
PyBuffer_Release(&pbuffer);
PyErr_SetString(PyExc_ValueError, "offset is negative"); PyErr_SetString(PyExc_ValueError, "offset is negative");
return NULL; return NULL;
} }
if (length < offset) { if (length < offset) {
PyBuffer_Release(&pbuffer);
PyErr_SetString(PyExc_ValueError, "buffer length < offset"); PyErr_SetString(PyExc_ValueError, "buffer length < offset");
return NULL; return NULL;
} }
@ -119,10 +124,12 @@ connection_sendbytes(ConnectionObject *self, PyObject *args)
size = length - offset; size = length - offset;
} else { } else {
if (size < 0) { if (size < 0) {
PyBuffer_Release(&pbuffer);
PyErr_SetString(PyExc_ValueError, "size is negative"); PyErr_SetString(PyExc_ValueError, "size is negative");
return NULL; return NULL;
} }
if (offset + size > length) { if (offset + size > length) {
PyBuffer_Release(&pbuffer);
PyErr_SetString(PyExc_ValueError, PyErr_SetString(PyExc_ValueError,
"buffer length < offset + size"); "buffer length < offset + size");
return NULL; return NULL;
@ -131,6 +138,7 @@ connection_sendbytes(ConnectionObject *self, PyObject *args)
res = conn_send_string(self, buffer + offset, size); res = conn_send_string(self, buffer + offset, size);
PyBuffer_Release(&pbuffer);
if (res < 0) if (res < 0)
return mp_SetError(PyExc_IOError, res); return mp_SetError(PyExc_IOError, res);
@ -187,21 +195,25 @@ connection_recvbytes_into(ConnectionObject *self, PyObject *args)
char *freeme = NULL, *buffer = NULL; char *freeme = NULL, *buffer = NULL;
Py_ssize_t res, length, offset = 0; Py_ssize_t res, length, offset = 0;
PyObject *result = NULL; PyObject *result = NULL;
Py_buffer pbuf;
if (!PyArg_ParseTuple(args, "w#|" F_PY_SSIZE_T,
&buffer, &length, &offset))
return NULL;
CHECK_READABLE(self); CHECK_READABLE(self);
if (!PyArg_ParseTuple(args, "w*|" F_PY_SSIZE_T,
&pbuf, &offset))
return NULL;
buffer = pbuf.buf;
length = pbuf.len;
if (offset < 0) { if (offset < 0) {
PyErr_SetString(PyExc_ValueError, "negative offset"); PyErr_SetString(PyExc_ValueError, "negative offset");
return NULL; goto _error;
} }
if (offset > length) { if (offset > length) {
PyErr_SetString(PyExc_ValueError, "offset too large"); PyErr_SetString(PyExc_ValueError, "offset too large");
return NULL; goto _error;
} }
res = conn_recv_string(self, buffer+offset, length-offset, res = conn_recv_string(self, buffer+offset, length-offset,
@ -231,11 +243,17 @@ connection_recvbytes_into(ConnectionObject *self, PyObject *args)
PyErr_SetObject(BufferTooShort, result); PyErr_SetObject(BufferTooShort, result);
Py_DECREF(result); Py_DECREF(result);
} }
return NULL; goto _error;
} }
} }
_cleanup:
PyBuffer_Release(&pbuf);
return result; return result;
_error:
result = NULL;
goto _cleanup;
} }
/* /*

View file

@ -1704,7 +1704,7 @@ getstring(PyObject* string, Py_ssize_t* p_length, int* p_charsize)
/* Release the buffer immediately --- possibly dangerous /* Release the buffer immediately --- possibly dangerous
but doing something else would require some re-factoring but doing something else would require some re-factoring
*/ */
PyObject_ReleaseBuffer(string, &view); PyBuffer_Release(&view);
if (bytes < 0) { if (bytes < 0) {
PyErr_SetString(PyExc_TypeError, "buffer has negative size"); PyErr_SetString(PyExc_TypeError, "buffer has negative size");

View file

@ -1567,11 +1567,11 @@ s_unpack(PyObject *self, PyObject *input)
PyErr_Format(StructError, PyErr_Format(StructError,
"unpack requires a bytes argument of length %zd", "unpack requires a bytes argument of length %zd",
soself->s_size); soself->s_size);
PyObject_ReleaseBuffer(input, &vbuf); PyBuffer_Release(&vbuf);
return NULL; return NULL;
} }
result = s_unpack_internal(soself, vbuf.buf); result = s_unpack_internal(soself, vbuf.buf);
PyObject_ReleaseBuffer(input, &vbuf); PyBuffer_Release(&vbuf);
return result; return result;
} }
@ -1609,11 +1609,11 @@ s_unpack_from(PyObject *self, PyObject *args, PyObject *kwds)
PyErr_Format(StructError, PyErr_Format(StructError,
"unpack_from requires a buffer of at least %zd bytes", "unpack_from requires a buffer of at least %zd bytes",
soself->s_size); soself->s_size);
PyObject_ReleaseBuffer(input, &vbuf); PyBuffer_Release(&vbuf);
return NULL; return NULL;
} }
result = s_unpack_internal(soself, (char*)vbuf.buf + offset); result = s_unpack_internal(soself, (char*)vbuf.buf + offset);
PyObject_ReleaseBuffer(input, &vbuf); PyBuffer_Release(&vbuf);
return result; return result;
} }

View file

@ -1820,6 +1820,8 @@ array_buffer_getbuf(arrayobject *self, Py_buffer *view, int flags)
if (view==NULL) goto finish; if (view==NULL) goto finish;
view->buf = (void *)self->ob_item; view->buf = (void *)self->ob_item;
view->obj = (PyObject*)self;
Py_INCREF(self);
if (view->buf == NULL) if (view->buf == NULL)
view->buf = (void *)emptybuf; view->buf = (void *)emptybuf;
view->len = (Py_SIZE(self)) * self->ob_descr->itemsize; view->len = (Py_SIZE(self)) * self->ob_descr->itemsize;

View file

@ -783,20 +783,24 @@ audioop_mul(PyObject *self, PyObject *args)
static PyObject * static PyObject *
audioop_tomono(PyObject *self, PyObject *args) audioop_tomono(PyObject *self, PyObject *args)
{ {
Py_buffer pcp;
signed char *cp, *ncp; signed char *cp, *ncp;
int len, size, val1 = 0, val2 = 0; int len, size, val1 = 0, val2 = 0;
double fac1, fac2, fval, maxval; double fac1, fac2, fval, maxval;
PyObject *rv; PyObject *rv;
int i; int i;
if ( !PyArg_ParseTuple(args, "s#idd:tomono", if ( !PyArg_ParseTuple(args, "s*idd:tomono",
&cp, &len, &size, &fac1, &fac2 ) ) &pcp, &size, &fac1, &fac2 ) )
return 0; return 0;
cp = pcp.buf;
len = pcp.len;
if ( size == 1 ) maxval = (double) 0x7f; if ( size == 1 ) maxval = (double) 0x7f;
else if ( size == 2 ) maxval = (double) 0x7fff; else if ( size == 2 ) maxval = (double) 0x7fff;
else if ( size == 4 ) maxval = (double) 0x7fffffff; else if ( size == 4 ) maxval = (double) 0x7fffffff;
else { else {
PyBuffer_Release(&pcp);
PyErr_SetString(AudioopError, "Size should be 1, 2 or 4"); PyErr_SetString(AudioopError, "Size should be 1, 2 or 4");
return 0; 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 == 2 ) *SHORTP(ncp, i/2) = (short)val1;
else if ( size == 4 ) *LONGP(ncp, i/2)= (Py_Int32)val1; else if ( size == 4 ) *LONGP(ncp, i/2)= (Py_Int32)val1;
} }
PyBuffer_Release(&pcp);
return rv; return rv;
} }

View file

@ -188,6 +188,7 @@ PyDoc_STRVAR(doc_a2b_uu, "(ascii) -> bin. Decode a line of uuencoded data");
static PyObject * static PyObject *
binascii_a2b_uu(PyObject *self, PyObject *args) binascii_a2b_uu(PyObject *self, PyObject *args)
{ {
Py_buffer pascii;
unsigned char *ascii_data, *bin_data; unsigned char *ascii_data, *bin_data;
int leftbits = 0; int leftbits = 0;
unsigned char this_ch; unsigned char this_ch;
@ -195,8 +196,10 @@ binascii_a2b_uu(PyObject *self, PyObject *args)
PyObject *rv; PyObject *rv;
Py_ssize_t ascii_len, bin_len; 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; return NULL;
ascii_data = pascii.buf;
ascii_len = pascii.len;
assert(ascii_len >= 0); assert(ascii_len >= 0);
@ -205,8 +208,10 @@ binascii_a2b_uu(PyObject *self, PyObject *args)
ascii_len--; ascii_len--;
/* Allocate the buffer */ /* Allocate the buffer */
if ( (rv=PyBytes_FromStringAndSize(NULL, bin_len)) == NULL ) if ( (rv=PyBytes_FromStringAndSize(NULL, bin_len)) == NULL ) {
PyBuffer_Release(&pascii);
return NULL; return NULL;
}
bin_data = (unsigned char *)PyBytes_AS_STRING(rv); bin_data = (unsigned char *)PyBytes_AS_STRING(rv);
for( ; bin_len > 0 ; ascii_len--, ascii_data++ ) { for( ; bin_len > 0 ; ascii_len--, ascii_data++ ) {
@ -258,6 +263,7 @@ binascii_a2b_uu(PyObject *self, PyObject *args)
return NULL; return NULL;
} }
} }
PyBuffer_Release(&pascii);
return rv; return rv;
} }
@ -266,6 +272,7 @@ PyDoc_STRVAR(doc_b2a_uu, "(bin) -> ascii. Uuencode line of data");
static PyObject * static PyObject *
binascii_b2a_uu(PyObject *self, PyObject *args) binascii_b2a_uu(PyObject *self, PyObject *args)
{ {
Py_buffer pbin;
unsigned char *ascii_data, *bin_data; unsigned char *ascii_data, *bin_data;
int leftbits = 0; int leftbits = 0;
unsigned char this_ch; unsigned char this_ch;
@ -273,17 +280,22 @@ binascii_b2a_uu(PyObject *self, PyObject *args)
PyObject *rv; PyObject *rv;
Py_ssize_t bin_len; 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; return NULL;
bin_data = pbin.buf;
bin_len = pbin.len;
if ( bin_len > 45 ) { if ( bin_len > 45 ) {
/* The 45 is a limit that appears in all uuencode's */ /* The 45 is a limit that appears in all uuencode's */
PyErr_SetString(Error, "At most 45 bytes at once"); PyErr_SetString(Error, "At most 45 bytes at once");
PyBuffer_Release(&pbin);
return NULL; return NULL;
} }
/* We're lazy and allocate to much (fixed up later) */ /* 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; return NULL;
}
ascii_data = (unsigned char *)PyBytes_AS_STRING(rv); ascii_data = (unsigned char *)PyBytes_AS_STRING(rv);
/* Store the length */ /* Store the length */
@ -312,6 +324,7 @@ binascii_b2a_uu(PyObject *self, PyObject *args)
Py_DECREF(rv); Py_DECREF(rv);
rv = NULL; rv = NULL;
} }
PyBuffer_Release(&pbin);
return rv; return rv;
} }
@ -346,6 +359,7 @@ PyDoc_STRVAR(doc_a2b_base64, "(ascii) -> bin. Decode a line of base64 data");
static PyObject * static PyObject *
binascii_a2b_base64(PyObject *self, PyObject *args) binascii_a2b_base64(PyObject *self, PyObject *args)
{ {
Py_buffer pascii;
unsigned char *ascii_data, *bin_data; unsigned char *ascii_data, *bin_data;
int leftbits = 0; int leftbits = 0;
unsigned char this_ch; unsigned char this_ch;
@ -354,19 +368,25 @@ binascii_a2b_base64(PyObject *self, PyObject *args)
Py_ssize_t ascii_len, bin_len; Py_ssize_t ascii_len, bin_len;
int quad_pos = 0; 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; return NULL;
ascii_data = pascii.buf;
ascii_len = pascii.len;
assert(ascii_len >= 0); 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(); return PyErr_NoMemory();
}
bin_len = ((ascii_len+3)/4)*3; /* Upper bound, corrected later */ bin_len = ((ascii_len+3)/4)*3; /* Upper bound, corrected later */
/* Allocate the buffer */ /* Allocate the buffer */
if ( (rv=PyBytes_FromStringAndSize(NULL, bin_len)) == NULL ) if ( (rv=PyBytes_FromStringAndSize(NULL, bin_len)) == NULL ) {
PyBuffer_Release(&pascii);
return NULL; return NULL;
}
bin_data = (unsigned char *)PyBytes_AS_STRING(rv); bin_data = (unsigned char *)PyBytes_AS_STRING(rv);
bin_len = 0; bin_len = 0;
@ -419,6 +439,7 @@ binascii_a2b_base64(PyObject *self, PyObject *args)
} }
if (leftbits != 0) { if (leftbits != 0) {
PyBuffer_Release(&pascii);
PyErr_SetString(Error, "Incorrect padding"); PyErr_SetString(Error, "Incorrect padding");
Py_DECREF(rv); Py_DECREF(rv);
return NULL; return NULL;
@ -438,6 +459,7 @@ binascii_a2b_base64(PyObject *self, PyObject *args)
Py_DECREF(rv); Py_DECREF(rv);
rv = PyBytes_FromStringAndSize("", 0); rv = PyBytes_FromStringAndSize("", 0);
} }
PyBuffer_Release(&pascii);
return rv; return rv;
} }
@ -446,6 +468,7 @@ PyDoc_STRVAR(doc_b2a_base64, "(bin) -> ascii. Base64-code line of data");
static PyObject * static PyObject *
binascii_b2a_base64(PyObject *self, PyObject *args) binascii_b2a_base64(PyObject *self, PyObject *args)
{ {
Py_buffer pbuf;
unsigned char *ascii_data, *bin_data; unsigned char *ascii_data, *bin_data;
int leftbits = 0; int leftbits = 0;
unsigned char this_ch; unsigned char this_ch;
@ -453,21 +476,26 @@ binascii_b2a_base64(PyObject *self, PyObject *args)
PyObject *rv; PyObject *rv;
Py_ssize_t bin_len; 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; return NULL;
bin_data = pbuf.buf;
bin_len = pbuf.len;
assert(bin_len >= 0); assert(bin_len >= 0);
if ( bin_len > BASE64_MAXBIN ) { if ( bin_len > BASE64_MAXBIN ) {
PyErr_SetString(Error, "Too much data for base64 line"); PyErr_SetString(Error, "Too much data for base64 line");
PyBuffer_Release(&pbuf);
return NULL; return NULL;
} }
/* We're lazy and allocate too much (fixed up later). /* We're lazy and allocate too much (fixed up later).
"+3" leaves room for up to two pad characters and a trailing "+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). */ 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; return NULL;
}
ascii_data = (unsigned char *)PyBytes_AS_STRING(rv); ascii_data = (unsigned char *)PyBytes_AS_STRING(rv);
for( ; bin_len > 0 ; bin_len--, bin_data++ ) { for( ; bin_len > 0 ; bin_len--, bin_data++ ) {
@ -498,6 +526,7 @@ binascii_b2a_base64(PyObject *self, PyObject *args)
Py_DECREF(rv); Py_DECREF(rv);
rv = NULL; rv = NULL;
} }
PyBuffer_Release(&pbuf);
return rv; return rv;
} }
@ -581,22 +610,29 @@ PyDoc_STRVAR(doc_rlecode_hqx, "Binhex RLE-code binary data");
static PyObject * static PyObject *
binascii_rlecode_hqx(PyObject *self, PyObject *args) binascii_rlecode_hqx(PyObject *self, PyObject *args)
{ {
Py_buffer pbuf;
unsigned char *in_data, *out_data; unsigned char *in_data, *out_data;
PyObject *rv; PyObject *rv;
unsigned char ch; unsigned char ch;
Py_ssize_t in, inend, len; 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; return NULL;
in_data = pbuf.buf;
len = pbuf.len;
assert(len >= 0); 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(); return PyErr_NoMemory();
}
/* Worst case: output is twice as big as input (fixed later) */ /* 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; return NULL;
}
out_data = (unsigned char *)PyBytes_AS_STRING(rv); out_data = (unsigned char *)PyBytes_AS_STRING(rv);
for( in=0; in<len; in++) { for( in=0; in<len; in++) {
@ -629,6 +665,7 @@ binascii_rlecode_hqx(PyObject *self, PyObject *args)
Py_DECREF(rv); Py_DECREF(rv);
rv = NULL; rv = NULL;
} }
PyBuffer_Release(&pbuf);
return rv; return rv;
} }
@ -637,6 +674,7 @@ PyDoc_STRVAR(doc_b2a_hqx, "Encode .hqx data");
static PyObject * static PyObject *
binascii_b2a_hqx(PyObject *self, PyObject *args) binascii_b2a_hqx(PyObject *self, PyObject *args)
{ {
Py_buffer pbin;
unsigned char *ascii_data, *bin_data; unsigned char *ascii_data, *bin_data;
int leftbits = 0; int leftbits = 0;
unsigned char this_ch; unsigned char this_ch;
@ -644,17 +682,23 @@ binascii_b2a_hqx(PyObject *self, PyObject *args)
PyObject *rv; PyObject *rv;
Py_ssize_t len; Py_ssize_t len;
if ( !PyArg_ParseTuple(args, "s#:b2a_hqx", &bin_data, &len) ) if ( !PyArg_ParseTuple(args, "s*:b2a_hqx", &pbin) )
return NULL; return NULL;
bin_data = pbin.buf;
len = pbin.len;
assert(len >= 0); 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(); return PyErr_NoMemory();
}
/* Allocate a buffer that is at least large enough */ /* 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; return NULL;
}
ascii_data = (unsigned char *)PyBytes_AS_STRING(rv); ascii_data = (unsigned char *)PyBytes_AS_STRING(rv);
for( ; len > 0 ; len--, bin_data++ ) { for( ; len > 0 ; len--, bin_data++ ) {
@ -678,6 +722,7 @@ binascii_b2a_hqx(PyObject *self, PyObject *args)
Py_DECREF(rv); Py_DECREF(rv);
rv = NULL; rv = NULL;
} }
PyBuffer_Release(&pbin);
return rv; return rv;
} }
@ -686,26 +731,35 @@ PyDoc_STRVAR(doc_rledecode_hqx, "Decode hexbin RLE-coded string");
static PyObject * static PyObject *
binascii_rledecode_hqx(PyObject *self, PyObject *args) binascii_rledecode_hqx(PyObject *self, PyObject *args)
{ {
Py_buffer pin;
unsigned char *in_data, *out_data; unsigned char *in_data, *out_data;
unsigned char in_byte, in_repeat; unsigned char in_byte, in_repeat;
PyObject *rv; PyObject *rv;
Py_ssize_t in_len, out_len, out_len_left; 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; return NULL;
in_data = pin.buf;
in_len = pin.len;
assert(in_len >= 0); assert(in_len >= 0);
/* Empty string is a special case */ /* Empty string is a special case */
if ( in_len == 0 ) if ( in_len == 0 ) {
PyBuffer_Release(&pin);
return PyBytes_FromStringAndSize("", 0); 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(); return PyErr_NoMemory();
}
/* Allocate a buffer of reasonable size. Resized when needed */ /* Allocate a buffer of reasonable size. Resized when needed */
out_len = in_len*2; 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; return NULL;
}
out_len_left = out_len; out_len_left = out_len;
out_data = (unsigned char *)PyBytes_AS_STRING(rv); out_data = (unsigned char *)PyBytes_AS_STRING(rv);
@ -718,6 +772,7 @@ binascii_rledecode_hqx(PyObject *self, PyObject *args)
if ( --in_len < 0 ) { \ if ( --in_len < 0 ) { \
PyErr_SetString(Incomplete, ""); \ PyErr_SetString(Incomplete, ""); \
Py_DECREF(rv); \ Py_DECREF(rv); \
PyBuffer_Release(&pin); \
return NULL; \ return NULL; \
} \ } \
b = *in_data++; \ b = *in_data++; \
@ -728,7 +783,7 @@ binascii_rledecode_hqx(PyObject *self, PyObject *args)
if ( --out_len_left < 0 ) { \ if ( --out_len_left < 0 ) { \
if ( out_len > PY_SSIZE_T_MAX / 2) return PyErr_NoMemory(); \ if ( out_len > PY_SSIZE_T_MAX / 2) return PyErr_NoMemory(); \
if (_PyBytes_Resize(&rv, 2*out_len) < 0) \ 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_data = (unsigned char *)PyBytes_AS_STRING(rv) \
+ out_len; \ + out_len; \
out_len_left = out_len-1; \ out_len_left = out_len-1; \
@ -783,6 +838,7 @@ binascii_rledecode_hqx(PyObject *self, PyObject *args)
Py_DECREF(rv); Py_DECREF(rv);
rv = NULL; rv = NULL;
} }
PyBuffer_Release(&pin);
return rv; return rv;
} }
@ -792,17 +848,21 @@ PyDoc_STRVAR(doc_crc_hqx,
static PyObject * static PyObject *
binascii_crc_hqx(PyObject *self, PyObject *args) binascii_crc_hqx(PyObject *self, PyObject *args)
{ {
Py_buffer pin;
unsigned char *bin_data; unsigned char *bin_data;
unsigned int crc; unsigned int crc;
Py_ssize_t len; 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; return NULL;
bin_data = pin.buf;
len = pin.len;
while(len-- > 0) { while(len-- > 0) {
crc=((crc<<8)&0xff00)^crctab_hqx[((crc>>8)&0xff)^*bin_data++]; crc=((crc<<8)&0xff00)^crctab_hqx[((crc>>8)&0xff)^*bin_data++];
} }
PyBuffer_Release(&pin);
return Py_BuildValue("i", crc); return Py_BuildValue("i", crc);
} }
@ -815,13 +875,17 @@ static PyObject *
binascii_crc32(PyObject *self, PyObject *args) binascii_crc32(PyObject *self, PyObject *args)
{ {
unsigned int crc32val = 0; /* crc32(0L, Z_NULL, 0) */ unsigned int crc32val = 0; /* crc32(0L, Z_NULL, 0) */
Py_buffer pbuf;
Byte *buf; Byte *buf;
Py_ssize_t len; Py_ssize_t len;
int signed_val; int signed_val;
if (!PyArg_ParseTuple(args, "s#|I:crc32", &buf, &len, &crc32val)) if (!PyArg_ParseTuple(args, "s*|I:crc32", &pbuf, &crc32val))
return NULL; return NULL;
buf = (Byte*)pbuf.buf;
len = pbuf.len;
signed_val = crc32(crc32val, buf, len); signed_val = crc32(crc32val, buf, len);
PyBuffer_Release(&pbuf);
return PyLong_FromUnsignedLong(signed_val & 0xffffffffU); return PyLong_FromUnsignedLong(signed_val & 0xffffffffU);
} }
#else /* USE_ZLIB_CRC32 */ #else /* USE_ZLIB_CRC32 */
@ -946,13 +1010,16 @@ static unsigned int crc_32_tab[256] = {
static PyObject * static PyObject *
binascii_crc32(PyObject *self, PyObject *args) binascii_crc32(PyObject *self, PyObject *args)
{ /* By Jim Ahlstrom; All rights transferred to CNRI */ { /* By Jim Ahlstrom; All rights transferred to CNRI */
Py_buffer pbin;
unsigned char *bin_data; unsigned char *bin_data;
unsigned int crc = 0; /* initial value of CRC */ unsigned int crc = 0; /* initial value of CRC */
Py_ssize_t len; Py_ssize_t len;
unsigned int result; 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; return NULL;
bin_data = pbin.buf;
len = pbin.len;
crc = ~ crc; crc = ~ crc;
while (len-- > 0) { while (len-- > 0) {
@ -961,6 +1028,7 @@ binascii_crc32(PyObject *self, PyObject *args)
} }
result = (crc ^ 0xFFFFFFFF); result = (crc ^ 0xFFFFFFFF);
PyBuffer_Release(&pbuf);
return PyLong_FromUnsignedLong(result & 0xffffffff); return PyLong_FromUnsignedLong(result & 0xffffffff);
} }
#endif /* USE_ZLIB_CRC32 */ #endif /* USE_ZLIB_CRC32 */
@ -969,22 +1037,29 @@ binascii_crc32(PyObject *self, PyObject *args)
static PyObject * static PyObject *
binascii_hexlify(PyObject *self, PyObject *args) binascii_hexlify(PyObject *self, PyObject *args)
{ {
Py_buffer parg;
char* argbuf; char* argbuf;
Py_ssize_t arglen; Py_ssize_t arglen;
PyObject *retval; PyObject *retval;
char* retbuf; char* retbuf;
Py_ssize_t i, j; Py_ssize_t i, j;
if (!PyArg_ParseTuple(args, "s#:b2a_hex", &argbuf, &arglen)) if (!PyArg_ParseTuple(args, "s*:b2a_hex", &parg))
return NULL; return NULL;
argbuf = parg.buf;
arglen = parg.len;
assert(arglen >= 0); assert(arglen >= 0);
if (arglen > PY_SSIZE_T_MAX / 2) if (arglen > PY_SSIZE_T_MAX / 2) {
PyBuffer_Release(&parg);
return PyErr_NoMemory(); return PyErr_NoMemory();
}
retval = PyBytes_FromStringAndSize(NULL, arglen*2); retval = PyBytes_FromStringAndSize(NULL, arglen*2);
if (!retval) if (!retval) {
PyBuffer_Release(&parg);
return NULL; return NULL;
}
retbuf = PyBytes_AS_STRING(retval); retbuf = PyBytes_AS_STRING(retval);
/* make hex version of string, taken from shamodule.c */ /* 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'; c = (c>9) ? c+'a'-10 : c + '0';
retbuf[j++] = c; retbuf[j++] = c;
} }
PyBuffer_Release(&parg);
return retval; return retval;
} }
@ -1024,14 +1100,17 @@ to_int(int c)
static PyObject * static PyObject *
binascii_unhexlify(PyObject *self, PyObject *args) binascii_unhexlify(PyObject *self, PyObject *args)
{ {
Py_buffer parg;
char* argbuf; char* argbuf;
Py_ssize_t arglen; Py_ssize_t arglen;
PyObject *retval; PyObject *retval;
char* retbuf; char* retbuf;
Py_ssize_t i, j; Py_ssize_t i, j;
if (!PyArg_ParseTuple(args, "s#:a2b_hex", &argbuf, &arglen)) if (!PyArg_ParseTuple(args, "s*:a2b_hex", &parg))
return NULL; return NULL;
argbuf = parg.buf;
arglen = parg.len;
assert(arglen >= 0); assert(arglen >= 0);
@ -1040,13 +1119,16 @@ binascii_unhexlify(PyObject *self, PyObject *args)
* raise an exception. * raise an exception.
*/ */
if (arglen % 2) { if (arglen % 2) {
PyBuffer_Release(&parg);
PyErr_SetString(Error, "Odd-length string"); PyErr_SetString(Error, "Odd-length string");
return NULL; return NULL;
} }
retval = PyBytes_FromStringAndSize(NULL, (arglen/2)); retval = PyBytes_FromStringAndSize(NULL, (arglen/2));
if (!retval) if (!retval) {
PyBuffer_Release(&parg);
return NULL; return NULL;
}
retbuf = PyBytes_AS_STRING(retval); retbuf = PyBytes_AS_STRING(retval);
for (i=j=0; i < arglen; i += 2) { for (i=j=0; i < arglen; i += 2) {
@ -1059,9 +1141,11 @@ binascii_unhexlify(PyObject *self, PyObject *args)
} }
retbuf[j++] = (top << 4) + bot; retbuf[j++] = (top << 4) + bot;
} }
PyBuffer_Release(&parg);
return retval; return retval;
finally: finally:
PyBuffer_Release(&parg);
Py_DECREF(retval); Py_DECREF(retval);
return NULL; return NULL;
} }
@ -1094,15 +1178,18 @@ binascii_a2b_qp(PyObject *self, PyObject *args, PyObject *kwargs)
{ {
Py_ssize_t in, out; Py_ssize_t in, out;
char ch; char ch;
Py_buffer pdata;
unsigned char *data, *odata; unsigned char *data, *odata;
Py_ssize_t datalen = 0; Py_ssize_t datalen = 0;
PyObject *rv; PyObject *rv;
static char *kwlist[] = {"data", "header", NULL}; static char *kwlist[] = {"data", "header", NULL};
int header = 0; int header = 0;
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s#|i", kwlist, &data, if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s*|i", kwlist, &pdata,
&datalen, &header)) &header))
return NULL; return NULL;
data = pdata.buf;
datalen = pdata.len;
/* We allocate the output same size as input, this is overkill. /* We allocate the output same size as input, this is overkill.
* The previous implementation used calloc() so we'll zero out the * 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); odata = (unsigned char *) PyMem_Malloc(datalen);
if (odata == NULL) { if (odata == NULL) {
PyBuffer_Release(&pdata);
PyErr_NoMemory(); PyErr_NoMemory();
return NULL; return NULL;
} }
@ -1160,9 +1248,11 @@ binascii_a2b_qp(PyObject *self, PyObject *args, PyObject *kwargs)
} }
} }
if ((rv = PyBytes_FromStringAndSize((char *)odata, out)) == NULL) { if ((rv = PyBytes_FromStringAndSize((char *)odata, out)) == NULL) {
PyBuffer_Release(&pdata);
PyMem_Free(odata); PyMem_Free(odata);
return NULL; return NULL;
} }
PyBuffer_Release(&pdata);
PyMem_Free(odata); PyMem_Free(odata);
return rv; return rv;
} }
@ -1193,6 +1283,7 @@ static PyObject*
binascii_b2a_qp (PyObject *self, PyObject *args, PyObject *kwargs) binascii_b2a_qp (PyObject *self, PyObject *args, PyObject *kwargs)
{ {
Py_ssize_t in, out; Py_ssize_t in, out;
Py_buffer pdata;
unsigned char *data, *odata; unsigned char *data, *odata;
Py_ssize_t datalen = 0, odatalen = 0; Py_ssize_t datalen = 0, odatalen = 0;
PyObject *rv; PyObject *rv;
@ -1206,9 +1297,11 @@ binascii_b2a_qp (PyObject *self, PyObject *args, PyObject *kwargs)
int crlf = 0; int crlf = 0;
unsigned char *p; unsigned char *p;
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s#|iii", kwlist, &data, if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s*|iii", kwlist, &pdata,
&datalen, &quotetabs, &istext, &header)) &quotetabs, &istext, &header))
return NULL; return NULL;
data = pdata.buf;
datalen = pdata.len;
/* See if this string is using CRLF line ends */ /* See if this string is using CRLF line ends */
/* XXX: this function has the side effect of converting all of /* 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); odata = (unsigned char *) PyMem_Malloc(odatalen);
if (odata == NULL) { if (odata == NULL) {
PyBuffer_Release(&pdata);
PyErr_NoMemory(); PyErr_NoMemory();
return NULL; return NULL;
} }
@ -1360,9 +1454,11 @@ binascii_b2a_qp (PyObject *self, PyObject *args, PyObject *kwargs)
} }
} }
if ((rv = PyBytes_FromStringAndSize((char *)odata, out)) == NULL) { if ((rv = PyBytes_FromStringAndSize((char *)odata, out)) == NULL) {
PyBuffer_Release(&pdata);
PyMem_Free(odata); PyMem_Free(odata);
return NULL; return NULL;
} }
PyBuffer_Release(&pdata);
PyMem_Free(odata); PyMem_Free(odata);
return rv; return rv;
} }

View file

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

View file

@ -608,18 +608,24 @@ MultibyteCodec_Decode(MultibyteCodecObject *self,
MultibyteCodec_State state; MultibyteCodec_State state;
MultibyteDecodeBuffer buf; MultibyteDecodeBuffer buf;
PyObject *errorcb; PyObject *errorcb;
Py_buffer pdata;
const char *data, *errors = NULL; const char *data, *errors = NULL;
Py_ssize_t datalen, finalsize; Py_ssize_t datalen, finalsize;
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s#|z:decode", if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s*|z:decode",
codeckwarglist, &data, &datalen, &errors)) codeckwarglist, &pdata, &errors))
return NULL; return NULL;
data = pdata.buf;
datalen = pdata.len;
errorcb = internal_error_callback(errors); errorcb = internal_error_callback(errors);
if (errorcb == NULL) if (errorcb == NULL) {
PyBuffer_Release(&pdata);
return NULL; return NULL;
}
if (datalen == 0) { if (datalen == 0) {
PyBuffer_Release(&pdata);
ERROR_DECREF(errorcb); ERROR_DECREF(errorcb);
return make_tuple(PyUnicode_FromUnicode(NULL, 0), 0); return make_tuple(PyUnicode_FromUnicode(NULL, 0), 0);
} }
@ -659,11 +665,13 @@ MultibyteCodec_Decode(MultibyteCodecObject *self,
if (PyUnicode_Resize(&buf.outobj, finalsize) == -1) if (PyUnicode_Resize(&buf.outobj, finalsize) == -1)
goto errorexit; goto errorexit;
PyBuffer_Release(&pdata);
Py_XDECREF(buf.excobj); Py_XDECREF(buf.excobj);
ERROR_DECREF(errorcb); ERROR_DECREF(errorcb);
return make_tuple(buf.outobj, datalen); return make_tuple(buf.outobj, datalen);
errorexit: errorexit:
PyBuffer_Release(&pdata);
ERROR_DECREF(errorcb); ERROR_DECREF(errorcb);
Py_XDECREF(buf.excobj); Py_XDECREF(buf.excobj);
Py_XDECREF(buf.outobj); Py_XDECREF(buf.outobj);

View file

@ -113,15 +113,18 @@ fcntl_ioctl(PyObject *self, PyObject *args)
unsigned int code; unsigned int code;
int arg; int arg;
int ret; int ret;
Py_buffer pstr;
char *str; char *str;
Py_ssize_t len; Py_ssize_t len;
int mutate_arg = 1; int mutate_arg = 1;
char buf[IOCTL_BUFSZ+1]; /* argument plus NUL byte */ 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, conv_descriptor, &fd, &code,
&str, &len, &mutate_arg)) { &pstr, &mutate_arg)) {
char *arg; char *arg;
str = pstr.buf;
len = pstr.len;
if (mutate_arg) { if (mutate_arg) {
if (len <= IOCTL_BUFSZ) { if (len <= IOCTL_BUFSZ) {
@ -135,6 +138,7 @@ fcntl_ioctl(PyObject *self, PyObject *args)
} }
else { else {
if (len > IOCTL_BUFSZ) { if (len > IOCTL_BUFSZ) {
PyBuffer_Release(&pstr);
PyErr_SetString(PyExc_ValueError, PyErr_SetString(PyExc_ValueError,
"ioctl string arg too long"); "ioctl string arg too long");
return NULL; return NULL;
@ -156,6 +160,7 @@ fcntl_ioctl(PyObject *self, PyObject *args)
if (mutate_arg && (len < IOCTL_BUFSZ)) { if (mutate_arg && (len < IOCTL_BUFSZ)) {
memcpy(str, buf, len); memcpy(str, buf, len);
} }
PyBuffer_Release(&pstr); /* No further access to str below this point */
if (ret < 0) { if (ret < 0) {
PyErr_SetFromErrno(PyExc_IOError); PyErr_SetFromErrno(PyExc_IOError);
return NULL; return NULL;
@ -169,9 +174,12 @@ fcntl_ioctl(PyObject *self, PyObject *args)
} }
PyErr_Clear(); PyErr_Clear();
if (PyArg_ParseTuple(args, "O&Is#:ioctl", if (PyArg_ParseTuple(args, "O&Is*:ioctl",
conv_descriptor, &fd, &code, &str, &len)) { conv_descriptor, &fd, &code, &pstr)) {
str = pstr.buf;
len = pstr.len;
if (len > IOCTL_BUFSZ) { if (len > IOCTL_BUFSZ) {
PyBuffer_Release(&pstr);
PyErr_SetString(PyExc_ValueError, PyErr_SetString(PyExc_ValueError,
"ioctl string arg too long"); "ioctl string arg too long");
return NULL; return NULL;
@ -182,9 +190,11 @@ fcntl_ioctl(PyObject *self, PyObject *args)
ret = ioctl(fd, code, buf); ret = ioctl(fd, code, buf);
Py_END_ALLOW_THREADS Py_END_ALLOW_THREADS
if (ret < 0) { if (ret < 0) {
PyBuffer_Release(&pstr);
PyErr_SetFromErrno(PyExc_IOError); PyErr_SetFromErrno(PyExc_IOError);
return NULL; return NULL;
} }
PyBuffer_Release(&pstr);
return PyBytes_FromStringAndSize(buf, len); return PyBytes_FromStringAndSize(buf, len);
} }

View file

@ -651,7 +651,7 @@ static int
mmap_buffer_getbuf(mmap_object *self, Py_buffer *view, int flags) mmap_buffer_getbuf(mmap_object *self, Py_buffer *view, int flags)
{ {
CHECK_VALID(-1); 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) (self->access == ACCESS_READ), flags) < 0)
return -1; return -1;
self->exports++; self->exports++;
@ -843,7 +843,7 @@ mmap_ass_subscript(mmap_object *self, PyObject *item, PyObject *value)
if (vbuf.len != slicelen) { if (vbuf.len != slicelen) {
PyErr_SetString(PyExc_IndexError, PyErr_SetString(PyExc_IndexError,
"mmap slice assignment is wrong size"); "mmap slice assignment is wrong size");
PyObject_ReleaseBuffer(value, &vbuf); PyBuffer_Release(&vbuf);
return -1; return -1;
} }
@ -862,7 +862,7 @@ mmap_ass_subscript(mmap_object *self, PyObject *item, PyObject *value)
self->data[cur] = ((char *)vbuf.buf)[i]; self->data[cur] = ((char *)vbuf.buf)[i];
} }
} }
PyObject_ReleaseBuffer(value, &vbuf); PyBuffer_Release(&vbuf);
return 0; return 0;
} }
else { else {

View file

@ -4894,15 +4894,16 @@ Write a string to a file descriptor.");
static PyObject * static PyObject *
posix_write(PyObject *self, PyObject *args) posix_write(PyObject *self, PyObject *args)
{ {
Py_buffer pbuf;
int fd; int fd;
Py_ssize_t size; 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; return NULL;
Py_BEGIN_ALLOW_THREADS Py_BEGIN_ALLOW_THREADS
size = write(fd, buffer, (size_t)size); size = write(fd, pbuf.buf, (size_t)pbuf.len);
Py_END_ALLOW_THREADS Py_END_ALLOW_THREADS
PyBuffer_Release(&pbuf);
if (size < 0) if (size < 0)
return posix_error(); return posix_error();
return PyLong_FromSsize_t(size); return PyLong_FromSsize_t(size);

View file

@ -2251,15 +2251,19 @@ sock_recv_into(PySocketSockObject *s, PyObject *args, PyObject *kwds)
int recvlen = 0, flags = 0; int recvlen = 0, flags = 0;
ssize_t readlen; ssize_t readlen;
Py_buffer pbuf;
char *buf; char *buf;
int buflen; int buflen;
/* Get the buffer's memory */ /* Get the buffer's memory */
if (!PyArg_ParseTupleAndKeywords(args, kwds, "w#|ii:recv_into", kwlist, if (!PyArg_ParseTupleAndKeywords(args, kwds, "w*|ii:recv_into", kwlist,
&buf, &buflen, &recvlen, &flags)) &pbuf, &recvlen, &flags))
return NULL; return NULL;
buf = pbuf.buf;
buflen = pbuf.len;
if (recvlen < 0) { if (recvlen < 0) {
PyBuffer_Release(&pbuf);
PyErr_SetString(PyExc_ValueError, PyErr_SetString(PyExc_ValueError,
"negative buffersize in recv_into"); "negative buffersize in recv_into");
return NULL; return NULL;
@ -2271,6 +2275,7 @@ sock_recv_into(PySocketSockObject *s, PyObject *args, PyObject *kwds)
/* Check if the buffer is large enough */ /* Check if the buffer is large enough */
if (buflen < recvlen) { if (buflen < recvlen) {
PyBuffer_Release(&pbuf);
PyErr_SetString(PyExc_ValueError, PyErr_SetString(PyExc_ValueError,
"buffer too small for requested bytes"); "buffer too small for requested bytes");
return NULL; return NULL;
@ -2280,9 +2285,11 @@ sock_recv_into(PySocketSockObject *s, PyObject *args, PyObject *kwds)
readlen = sock_recv_guts(s, buf, recvlen, flags); readlen = sock_recv_guts(s, buf, recvlen, flags);
if (readlen < 0) { if (readlen < 0) {
/* Return an error. */ /* Return an error. */
PyBuffer_Release(&pbuf);
return NULL; return NULL;
} }
PyBuffer_Release(&pbuf);
/* Return the number of bytes read. Note that we do not do anything /* Return the number of bytes read. Note that we do not do anything
special here in the case that readlen < recvlen. */ special here in the case that readlen < recvlen. */
return PyLong_FromSsize_t(readlen); return PyLong_FromSsize_t(readlen);
@ -2424,18 +2431,22 @@ sock_recvfrom_into(PySocketSockObject *s, PyObject *args, PyObject* kwds)
int recvlen = 0, flags = 0; int recvlen = 0, flags = 0;
ssize_t readlen; ssize_t readlen;
Py_buffer pbuf;
char *buf; char *buf;
int buflen; int buflen;
PyObject *addr = NULL; PyObject *addr = NULL;
if (!PyArg_ParseTupleAndKeywords(args, kwds, "w#|ii:recvfrom_into", if (!PyArg_ParseTupleAndKeywords(args, kwds, "w*|ii:recvfrom_into",
kwlist, &buf, &buflen, kwlist, &pbuf,
&recvlen, &flags)) &recvlen, &flags))
return NULL; return NULL;
buf = pbuf.buf;
buflen = pbuf.len;
assert(buf != 0 && buflen > 0); assert(buf != 0 && buflen > 0);
if (recvlen < 0) { if (recvlen < 0) {
PyBuffer_Release(&pbuf);
PyErr_SetString(PyExc_ValueError, PyErr_SetString(PyExc_ValueError,
"negative buffersize in recvfrom_into"); "negative buffersize in recvfrom_into");
return NULL; return NULL;
@ -2447,11 +2458,13 @@ sock_recvfrom_into(PySocketSockObject *s, PyObject *args, PyObject* kwds)
readlen = sock_recvfrom_guts(s, buf, recvlen, flags, &addr); readlen = sock_recvfrom_guts(s, buf, recvlen, flags, &addr);
if (readlen < 0) { if (readlen < 0) {
PyBuffer_Release(&pbuf);
/* Return an error */ /* Return an error */
Py_XDECREF(addr); Py_XDECREF(addr);
return NULL; return NULL;
} }
PyBuffer_Release(&pbuf);
/* Return the number of bytes read and the address. Note that we do /* Return the number of bytes read and the address. Note that we do
not do anything special here in the case that readlen < recvlen. */ not do anything special here in the case that readlen < recvlen. */
return Py_BuildValue("lN", readlen, addr); return Py_BuildValue("lN", readlen, addr);
@ -2470,12 +2483,17 @@ sock_send(PySocketSockObject *s, PyObject *args)
{ {
char *buf; char *buf;
int len, n = -1, flags = 0, timeout; 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; return NULL;
if (!IS_SELECTABLE(s)) if (!IS_SELECTABLE(s)) {
PyBuffer_Release(&pbuf);
return select_error(); return select_error();
}
buf = pbuf.buf;
len = pbuf.len;
Py_BEGIN_ALLOW_THREADS Py_BEGIN_ALLOW_THREADS
timeout = internal_select(s, 1); timeout = internal_select(s, 1);
@ -2487,6 +2505,8 @@ sock_send(PySocketSockObject *s, PyObject *args)
#endif #endif
Py_END_ALLOW_THREADS Py_END_ALLOW_THREADS
PyBuffer_Release(&pbuf);
if (timeout == 1) { if (timeout == 1) {
PyErr_SetString(socket_timeout, "timed out"); PyErr_SetString(socket_timeout, "timed out");
return NULL; return NULL;
@ -2511,12 +2531,17 @@ sock_sendall(PySocketSockObject *s, PyObject *args)
{ {
char *buf; char *buf;
int len, n = -1, flags = 0, timeout; 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; return NULL;
buf = pbuf.buf;
len = pbuf.len;
if (!IS_SELECTABLE(s)) if (!IS_SELECTABLE(s)) {
PyBuffer_Release(&pbuf);
return select_error(); return select_error();
}
Py_BEGIN_ALLOW_THREADS Py_BEGIN_ALLOW_THREADS
do { do {
@ -2535,6 +2560,7 @@ sock_sendall(PySocketSockObject *s, PyObject *args)
len -= n; len -= n;
} while (len > 0); } while (len > 0);
Py_END_ALLOW_THREADS Py_END_ALLOW_THREADS
PyBuffer_Release(&pbuf);
if (timeout == 1) { if (timeout == 1) {
PyErr_SetString(socket_timeout, "timed out"); PyErr_SetString(socket_timeout, "timed out");
@ -2561,24 +2587,32 @@ to tell how much data has been sent.");
static PyObject * static PyObject *
sock_sendto(PySocketSockObject *s, PyObject *args) sock_sendto(PySocketSockObject *s, PyObject *args)
{ {
Py_buffer pbuf;
PyObject *addro; PyObject *addro;
char *buf; char *buf;
Py_ssize_t len;
sock_addr_t addrbuf; sock_addr_t addrbuf;
int addrlen, len, n = -1, flags, timeout; int addrlen, n = -1, flags, timeout;
flags = 0; flags = 0;
if (!PyArg_ParseTuple(args, "y#O:sendto", &buf, &len, &addro)) { if (!PyArg_ParseTuple(args, "y*O:sendto", &pbuf, &addro)) {
PyErr_Clear(); PyErr_Clear();
if (!PyArg_ParseTuple(args, "y#iO:sendto", if (!PyArg_ParseTuple(args, "y*iO:sendto",
&buf, &len, &flags, &addro)) &pbuf, &flags, &addro))
return NULL; return NULL;
} }
buf = pbuf.buf;
len = pbuf.len;
if (!IS_SELECTABLE(s)) if (!IS_SELECTABLE(s)) {
PyBuffer_Release(&pbuf);
return select_error(); return select_error();
}
if (!getsockaddrarg(s, addro, SAS2SA(&addrbuf), &addrlen)) if (!getsockaddrarg(s, addro, SAS2SA(&addrbuf), &addrlen)) {
PyBuffer_Release(&pbuf);
return NULL; return NULL;
}
Py_BEGIN_ALLOW_THREADS Py_BEGIN_ALLOW_THREADS
timeout = internal_select(s, 1); 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); n = sendto(s->sock_fd, buf, len, flags, SAS2SA(&addrbuf), addrlen);
Py_END_ALLOW_THREADS Py_END_ALLOW_THREADS
PyBuffer_Release(&pbuf);
if (timeout == 1) { if (timeout == 1) {
PyErr_SetString(socket_timeout, "timed out"); PyErr_SetString(socket_timeout, "timed out");
return NULL; return NULL;

View file

@ -118,18 +118,22 @@ static PyObject *
PyZlib_compress(PyObject *self, PyObject *args) PyZlib_compress(PyObject *self, PyObject *args)
{ {
PyObject *ReturnVal = NULL; PyObject *ReturnVal = NULL;
Py_buffer pinput;
Byte *input, *output; Byte *input, *output;
int length, level=Z_DEFAULT_COMPRESSION, err; int length, level=Z_DEFAULT_COMPRESSION, err;
z_stream zst; z_stream zst;
/* require Python string object, optional 'level' arg */ /* 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; return NULL;
input = pinput.buf;
length = pinput.len;
zst.avail_out = length + length/1000 + 12 + 1; zst.avail_out = length + length/1000 + 12 + 1;
output = (Byte*)malloc(zst.avail_out); output = (Byte*)malloc(zst.avail_out);
if (output == NULL) { if (output == NULL) {
PyBuffer_Release(&pinput);
PyErr_SetString(PyExc_MemoryError, PyErr_SetString(PyExc_MemoryError,
"Can't allocate memory to compress data"); "Can't allocate memory to compress data");
return NULL; return NULL;
@ -180,6 +184,7 @@ PyZlib_compress(PyObject *self, PyObject *args)
zlib_error(zst, err, "while finishing compression"); zlib_error(zst, err, "while finishing compression");
error: error:
PyBuffer_Release(&pinput);
free(output); free(output);
return ReturnVal; return ReturnVal;
@ -195,15 +200,18 @@ static PyObject *
PyZlib_decompress(PyObject *self, PyObject *args) PyZlib_decompress(PyObject *self, PyObject *args)
{ {
PyObject *result_str; PyObject *result_str;
Py_buffer pinput;
Byte *input; Byte *input;
int length, err; int length, err;
int wsize=DEF_WBITS; int wsize=DEF_WBITS;
Py_ssize_t r_strlen=DEFAULTALLOC; Py_ssize_t r_strlen=DEFAULTALLOC;
z_stream zst; z_stream zst;
if (!PyArg_ParseTuple(args, "s#|in:decompress", if (!PyArg_ParseTuple(args, "s*|in:decompress",
&input, &length, &wsize, &r_strlen)) &pinput, &wsize, &r_strlen))
return NULL; return NULL;
input = pinput.buf;
length = pinput.len;
if (r_strlen <= 0) if (r_strlen <= 0)
r_strlen = 1; r_strlen = 1;
@ -211,8 +219,10 @@ PyZlib_decompress(PyObject *self, PyObject *args)
zst.avail_in = length; zst.avail_in = length;
zst.avail_out = r_strlen; 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; return NULL;
}
zst.zalloc = (alloc_func)NULL; zst.zalloc = (alloc_func)NULL;
zst.zfree = (free_func)Z_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) if (PyByteArray_Resize(result_str, zst.total_out) < 0)
goto error; goto error;
PyBuffer_Release(&pinput);
return result_str; return result_str;
error: error:
PyBuffer_Release(&pinput);
Py_XDECREF(result_str); Py_XDECREF(result_str);
return NULL; return NULL;
} }
@ -396,14 +408,19 @@ PyZlib_objcompress(compobject *self, PyObject *args)
{ {
int err, inplen, length = DEFAULTALLOC; int err, inplen, length = DEFAULTALLOC;
PyObject *RetVal; PyObject *RetVal;
Py_buffer pinput;
Byte *input; Byte *input;
unsigned long start_total_out; unsigned long start_total_out;
if (!PyArg_ParseTuple(args, "s#:compress", &input, &inplen)) if (!PyArg_ParseTuple(args, "s*:compress", &pinput))
return NULL; 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; return NULL;
}
ENTER_ZLIB ENTER_ZLIB
@ -452,6 +469,7 @@ PyZlib_objcompress(compobject *self, PyObject *args)
error: error:
LEAVE_ZLIB LEAVE_ZLIB
PyBuffer_Release(&pinput);
return RetVal; return RetVal;
} }
@ -472,13 +490,17 @@ PyZlib_objdecompress(compobject *self, PyObject *args)
int err, inplen, old_length, length = DEFAULTALLOC; int err, inplen, old_length, length = DEFAULTALLOC;
int max_length = 0; int max_length = 0;
PyObject *RetVal; PyObject *RetVal;
Py_buffer pinput;
Byte *input; Byte *input;
unsigned long start_total_out; unsigned long start_total_out;
if (!PyArg_ParseTuple(args, "s#|i:decompress", &input, if (!PyArg_ParseTuple(args, "s*|i:decompress", &pinput,
&inplen, &max_length)) &max_length))
return NULL; return NULL;
input = pinput.buf;
inplen = pinput.len;
if (max_length < 0) { if (max_length < 0) {
PyBuffer_Release(&pinput);
PyErr_SetString(PyExc_ValueError, PyErr_SetString(PyExc_ValueError,
"max_length must be greater than zero"); "max_length must be greater than zero");
return NULL; return NULL;
@ -487,8 +509,10 @@ PyZlib_objdecompress(compobject *self, PyObject *args)
/* limit amount of data allocated to max_length */ /* limit amount of data allocated to max_length */
if (max_length && length > max_length) if (max_length && length > 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; return NULL;
}
ENTER_ZLIB ENTER_ZLIB
@ -577,7 +601,7 @@ PyZlib_objdecompress(compobject *self, PyObject *args)
error: error:
LEAVE_ZLIB LEAVE_ZLIB
PyBuffer_Release(&pinput);
return RetVal; return RetVal;
} }
@ -916,12 +940,13 @@ static PyObject *
PyZlib_crc32(PyObject *self, PyObject *args) PyZlib_crc32(PyObject *self, PyObject *args)
{ {
unsigned int crc32val = 0; /* crc32(0L, Z_NULL, 0) */ unsigned int crc32val = 0; /* crc32(0L, Z_NULL, 0) */
Byte *buf; Py_buffer pbuf;
int len, signed_val; int signed_val;
if (!PyArg_ParseTuple(args, "s#|I:crc32", &buf, &len, &crc32val)) if (!PyArg_ParseTuple(args, "s*|I:crc32", &pbuf, &crc32val))
return NULL; 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); return PyLong_FromUnsignedLong(signed_val & 0xffffffffU);
} }

View 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); 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 static int
_IsFortranContiguous(Py_buffer *view) _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(dest, &view_dest, PyBUF_FULL) != 0) return -1;
if (PyObject_GetBuffer(src, &view_src, PyBUF_FULL_RO) != 0) { if (PyObject_GetBuffer(src, &view_src, PyBUF_FULL_RO) != 0) {
PyObject_ReleaseBuffer(dest, &view_dest); PyBuffer_Release(&view_dest);
return -1; return -1;
} }
if (view_dest.len < view_src.len) { if (view_dest.len < view_src.len) {
PyErr_SetString(PyExc_BufferError, PyErr_SetString(PyExc_BufferError,
"destination is too small to receive data from source"); "destination is too small to receive data from source");
PyObject_ReleaseBuffer(dest, &view_dest); PyBuffer_Release(&view_dest);
PyObject_ReleaseBuffer(src, &view_src); PyBuffer_Release(&view_src);
return -1; return -1;
} }
@ -608,8 +598,8 @@ int PyObject_CopyData(PyObject *dest, PyObject *src)
PyBuffer_IsContiguous(&view_src, 'F'))) { PyBuffer_IsContiguous(&view_src, 'F'))) {
/* simplest copy is all that is needed */ /* simplest copy is all that is needed */
memcpy(view_dest.buf, view_src.buf, view_src.len); memcpy(view_dest.buf, view_src.buf, view_src.len);
PyObject_ReleaseBuffer(dest, &view_dest); PyBuffer_Release(&view_dest);
PyObject_ReleaseBuffer(src, &view_src); PyBuffer_Release(&view_src);
return 0; 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); indices = (Py_ssize_t *)PyMem_Malloc(sizeof(Py_ssize_t)*view_src.ndim);
if (indices == NULL) { if (indices == NULL) {
PyErr_NoMemory(); PyErr_NoMemory();
PyObject_ReleaseBuffer(dest, &view_dest); PyBuffer_Release(&view_dest);
PyObject_ReleaseBuffer(src, &view_src); PyBuffer_Release(&view_src);
return -1; return -1;
} }
for (k=0; k<view_src.ndim;k++) { 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); memcpy(dptr, sptr, view_src.itemsize);
} }
PyMem_Free(indices); PyMem_Free(indices);
PyObject_ReleaseBuffer(dest, &view_dest); PyBuffer_Release(&view_dest);
PyObject_ReleaseBuffer(src, &view_src); PyBuffer_Release(&view_src);
return 0; return 0;
} }
@ -668,7 +658,7 @@ PyBuffer_FillContiguousStrides(int nd, Py_ssize_t *shape,
} }
int 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) int readonly, int flags)
{ {
if (view == NULL) return 0; if (view == NULL) return 0;
@ -679,6 +669,7 @@ PyBuffer_FillInfo(Py_buffer *view, void *buf, Py_ssize_t len,
return -1; return -1;
} }
view->obj = obj;
view->buf = buf; view->buf = buf;
view->len = len; view->len = len;
view->readonly = readonly; view->readonly = readonly;
@ -698,6 +689,17 @@ PyBuffer_FillInfo(Py_buffer *view, void *buf, Py_ssize_t len,
return 0; 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 *
PyObject_Format(PyObject *obj, PyObject *format_spec) PyObject_Format(PyObject *obj, PyObject *format_spec)
{ {

View file

@ -69,7 +69,7 @@ bytes_getbuffer(PyByteArrayObject *obj, Py_buffer *view, int flags)
ptr = ""; ptr = "";
else else
ptr = obj->ob_bytes; 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) { if (ret >= 0) {
obj->ob_exports++; obj->ob_exports++;
} }
@ -248,9 +248,9 @@ PyByteArray_Concat(PyObject *a, PyObject *b)
done: done:
if (va.len != -1) if (va.len != -1)
PyObject_ReleaseBuffer(a, &va); PyBuffer_Release(&va);
if (vb.len != -1) if (vb.len != -1)
PyObject_ReleaseBuffer(b, &vb); PyBuffer_Release(&vb);
return (PyObject *)result; return (PyObject *)result;
} }
@ -278,7 +278,7 @@ bytes_iconcat(PyByteArrayObject *self, PyObject *other)
mysize = Py_SIZE(self); mysize = Py_SIZE(self);
size = mysize + vo.len; size = mysize + vo.len;
if (size < 0) { if (size < 0) {
PyObject_ReleaseBuffer(other, &vo); PyBuffer_Release(&vo);
return PyErr_NoMemory(); return PyErr_NoMemory();
} }
if (size < self->ob_alloc) { 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 */ self->ob_bytes[Py_SIZE(self)] = '\0'; /* Trailing null byte */
} }
else if (PyByteArray_Resize((PyObject *)self, size) < 0) { else if (PyByteArray_Resize((PyObject *)self, size) < 0) {
PyObject_ReleaseBuffer(other, &vo); PyBuffer_Release(&vo);
return NULL; return NULL;
} }
memcpy(self->ob_bytes + mysize, vo.buf, vo.len); memcpy(self->ob_bytes + mysize, vo.buf, vo.len);
PyObject_ReleaseBuffer(other, &vo); PyBuffer_Release(&vo);
Py_INCREF(self); Py_INCREF(self);
return (PyObject *)self; return (PyObject *)self;
} }
@ -501,7 +501,7 @@ bytes_setslice(PyByteArrayObject *self, Py_ssize_t lo, Py_ssize_t hi,
finish: finish:
if (vbytes.len != -1) if (vbytes.len != -1)
PyObject_ReleaseBuffer(values, &vbytes); PyBuffer_Release(&vbytes);
return res; return res;
} }
@ -767,10 +767,10 @@ bytes_init(PyByteArrayObject *self, PyObject *args, PyObject *kwds)
if (PyByteArray_Resize((PyObject *)self, size) < 0) goto fail; if (PyByteArray_Resize((PyObject *)self, size) < 0) goto fail;
if (PyBuffer_ToContiguous(self->ob_bytes, &view, size, 'C') < 0) if (PyBuffer_ToContiguous(self->ob_bytes, &view, size, 'C') < 0)
goto fail; goto fail;
PyObject_ReleaseBuffer(arg, &view); PyBuffer_Release(&view);
return 0; return 0;
fail: fail:
PyObject_ReleaseBuffer(arg, &view); PyBuffer_Release(&view);
return -1; return -1;
} }
@ -954,7 +954,7 @@ bytes_richcompare(PyObject *self, PyObject *other, int op)
other_size = _getbuffer(other, &other_bytes); other_size = _getbuffer(other, &other_bytes);
if (other_size < 0) { if (other_size < 0) {
PyErr_Clear(); PyErr_Clear();
PyObject_ReleaseBuffer(self, &self_bytes); PyBuffer_Release(&self_bytes);
Py_INCREF(Py_NotImplemented); Py_INCREF(Py_NotImplemented);
return Py_NotImplemented; return Py_NotImplemented;
} }
@ -989,8 +989,8 @@ bytes_richcompare(PyObject *self, PyObject *other, int op)
} }
res = cmp ? Py_True : Py_False; res = cmp ? Py_True : Py_False;
PyObject_ReleaseBuffer(self, &self_bytes); PyBuffer_Release(&self_bytes);
PyObject_ReleaseBuffer(other, &other_bytes); PyBuffer_Release(&other_bytes);
Py_INCREF(res); Py_INCREF(res);
return res; return res;
} }
@ -998,6 +998,11 @@ bytes_richcompare(PyObject *self, PyObject *other, int op)
static void static void
bytes_dealloc(PyByteArrayObject *self) 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) { if (self->ob_bytes != 0) {
PyMem_Free(self->ob_bytes); PyMem_Free(self->ob_bytes);
} }
@ -1065,7 +1070,7 @@ bytes_find_internal(PyByteArrayObject *self, PyObject *args, int dir)
res = stringlib_rfind_slice( res = stringlib_rfind_slice(
PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self), PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self),
subbuf.buf, subbuf.len, start, end); subbuf.buf, subbuf.len, start, end);
PyObject_ReleaseBuffer(subobj, &subbuf); PyBuffer_Release(&subbuf);
return res; return res;
} }
@ -1115,7 +1120,7 @@ bytes_count(PyByteArrayObject *self, PyObject *args)
count_obj = PyLong_FromSsize_t( count_obj = PyLong_FromSsize_t(
stringlib_count(str + start, end - start, vsub.buf, vsub.len) stringlib_count(str + start, end - start, vsub.buf, vsub.len)
); );
PyObject_ReleaseBuffer(sub_obj, &vsub); PyBuffer_Release(&vsub);
return count_obj; return count_obj;
} }
@ -1191,7 +1196,7 @@ bytes_contains(PyObject *self, PyObject *arg)
return -1; return -1;
pos = stringlib_find(PyByteArray_AS_STRING(self), Py_SIZE(self), pos = stringlib_find(PyByteArray_AS_STRING(self), Py_SIZE(self),
varg.buf, varg.len, 0); varg.buf, varg.len, 0);
PyObject_ReleaseBuffer(arg, &varg); PyBuffer_Release(&varg);
return pos >= 0; return pos >= 0;
} }
if (ival < 0 || ival >= 256) { 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); rv = ! memcmp(str+start, vsubstr.buf, vsubstr.len);
done: done:
PyObject_ReleaseBuffer(substr, &vsubstr); PyBuffer_Release(&vsubstr);
return rv; return rv;
} }
@ -1421,9 +1426,9 @@ bytes_translate(PyByteArrayObject *self, PyObject *args)
PyByteArray_Resize(result, output - output_start); PyByteArray_Resize(result, output - output_start);
done: done:
PyObject_ReleaseBuffer(tableobj, &vtable); PyBuffer_Release(&vtable);
if (delobj != NULL) if (delobj != NULL)
PyObject_ReleaseBuffer(delobj, &vdel); PyBuffer_Release(&vdel);
return result; return result;
} }
@ -2042,7 +2047,7 @@ bytes_replace(PyByteArrayObject *self, PyObject *args)
if (_getbuffer(from, &vfrom) < 0) if (_getbuffer(from, &vfrom) < 0)
return NULL; return NULL;
if (_getbuffer(to, &vto) < 0) { if (_getbuffer(to, &vto) < 0) {
PyObject_ReleaseBuffer(from, &vfrom); PyBuffer_Release(&vfrom);
return NULL; return NULL;
} }
@ -2050,8 +2055,8 @@ bytes_replace(PyByteArrayObject *self, PyObject *args)
vfrom.buf, vfrom.len, vfrom.buf, vfrom.len,
vto.buf, vto.len, count); vto.buf, vto.len, count);
PyObject_ReleaseBuffer(from, &vfrom); PyBuffer_Release(&vfrom);
PyObject_ReleaseBuffer(to, &vto); PyBuffer_Release(&vto);
return res; return res;
} }
@ -2207,7 +2212,7 @@ bytes_split(PyByteArrayObject *self, PyObject *args)
if (n == 0) { if (n == 0) {
PyErr_SetString(PyExc_ValueError, "empty separator"); PyErr_SetString(PyExc_ValueError, "empty separator");
PyObject_ReleaseBuffer(subobj, &vsub); PyBuffer_Release(&vsub);
return NULL; return NULL;
} }
if (n == 1) if (n == 1)
@ -2215,7 +2220,7 @@ bytes_split(PyByteArrayObject *self, PyObject *args)
list = PyList_New(PREALLOC_SIZE(maxsplit)); list = PyList_New(PREALLOC_SIZE(maxsplit));
if (list == NULL) { if (list == NULL) {
PyObject_ReleaseBuffer(subobj, &vsub); PyBuffer_Release(&vsub);
return NULL; return NULL;
} }
@ -2243,12 +2248,12 @@ bytes_split(PyByteArrayObject *self, PyObject *args)
#endif #endif
SPLIT_ADD(s, i, len); SPLIT_ADD(s, i, len);
FIX_PREALLOC_SIZE(list); FIX_PREALLOC_SIZE(list);
PyObject_ReleaseBuffer(subobj, &vsub); PyBuffer_Release(&vsub);
return list; return list;
onError: onError:
Py_DECREF(list); Py_DECREF(list);
PyObject_ReleaseBuffer(subobj, &vsub); PyBuffer_Release(&vsub);
return NULL; return NULL;
} }
@ -2439,7 +2444,7 @@ bytes_rsplit(PyByteArrayObject *self, PyObject *args)
if (n == 0) { if (n == 0) {
PyErr_SetString(PyExc_ValueError, "empty separator"); PyErr_SetString(PyExc_ValueError, "empty separator");
PyObject_ReleaseBuffer(subobj, &vsub); PyBuffer_Release(&vsub);
return NULL; return NULL;
} }
else if (n == 1) else if (n == 1)
@ -2447,7 +2452,7 @@ bytes_rsplit(PyByteArrayObject *self, PyObject *args)
list = PyList_New(PREALLOC_SIZE(maxsplit)); list = PyList_New(PREALLOC_SIZE(maxsplit));
if (list == NULL) { if (list == NULL) {
PyObject_ReleaseBuffer(subobj, &vsub); PyBuffer_Release(&vsub);
return NULL; return NULL;
} }
@ -2468,12 +2473,12 @@ bytes_rsplit(PyByteArrayObject *self, PyObject *args)
FIX_PREALLOC_SIZE(list); FIX_PREALLOC_SIZE(list);
if (PyList_Reverse(list) < 0) if (PyList_Reverse(list) < 0)
goto onError; goto onError;
PyObject_ReleaseBuffer(subobj, &vsub); PyBuffer_Release(&vsub);
return list; return list;
onError: onError:
Py_DECREF(list); Py_DECREF(list);
PyObject_ReleaseBuffer(subobj, &vsub); PyBuffer_Release(&vsub);
return NULL; return NULL;
} }
@ -2749,7 +2754,7 @@ bytes_strip(PyByteArrayObject *self, PyObject *args)
else else
right = rstrip_helper(myptr, mysize, argptr, argsize); right = rstrip_helper(myptr, mysize, argptr, argsize);
if (arg != Py_None) if (arg != Py_None)
PyObject_ReleaseBuffer(arg, &varg); PyBuffer_Release(&varg);
return PyByteArray_FromStringAndSize(self->ob_bytes + left, right - left); 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); left = lstrip_helper(myptr, mysize, argptr, argsize);
right = mysize; right = mysize;
if (arg != Py_None) if (arg != Py_None)
PyObject_ReleaseBuffer(arg, &varg); PyBuffer_Release(&varg);
return PyByteArray_FromStringAndSize(self->ob_bytes + left, right - left); return PyByteArray_FromStringAndSize(self->ob_bytes + left, right - left);
} }
@ -2817,7 +2822,7 @@ bytes_rstrip(PyByteArrayObject *self, PyObject *args)
left = 0; left = 0;
right = rstrip_helper(myptr, mysize, argptr, argsize); right = rstrip_helper(myptr, mysize, argptr, argsize);
if (arg != Py_None) if (arg != Py_None)
PyObject_ReleaseBuffer(arg, &varg); PyBuffer_Release(&varg);
return PyByteArray_FromStringAndSize(self->ob_bytes + left, right - left); return PyByteArray_FromStringAndSize(self->ob_bytes + left, right - left);
} }

View file

@ -710,9 +710,9 @@ string_concat(PyObject *a, PyObject *b)
done: done:
if (va.len != -1) if (va.len != -1)
PyObject_ReleaseBuffer(a, &va); PyBuffer_Release(&va);
if (vb.len != -1) if (vb.len != -1)
PyObject_ReleaseBuffer(b, &vb); PyBuffer_Release(&vb);
return result; return result;
} }
@ -781,7 +781,7 @@ string_contains(PyObject *self, PyObject *arg)
return -1; return -1;
pos = stringlib_find(PyBytes_AS_STRING(self), Py_SIZE(self), pos = stringlib_find(PyBytes_AS_STRING(self), Py_SIZE(self),
varg.buf, varg.len, 0); varg.buf, varg.len, 0);
PyObject_ReleaseBuffer(arg, &varg); PyBuffer_Release(&varg);
return pos >= 0; return pos >= 0;
} }
if (ival < 0 || ival >= 256) { if (ival < 0 || ival >= 256) {
@ -964,7 +964,7 @@ string_subscript(PyBytesObject* self, PyObject* item)
static int static int
string_buffer_getbuffer(PyBytesObject *self, Py_buffer *view, int flags) 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); 1, flags);
} }
@ -1160,7 +1160,7 @@ string_split(PyBytesObject *self, PyObject *args)
if (n == 0) { if (n == 0) {
PyErr_SetString(PyExc_ValueError, "empty separator"); PyErr_SetString(PyExc_ValueError, "empty separator");
PyObject_ReleaseBuffer(subobj, &vsub); PyBuffer_Release(&vsub);
return NULL; return NULL;
} }
else if (n == 1) else if (n == 1)
@ -1168,7 +1168,7 @@ string_split(PyBytesObject *self, PyObject *args)
list = PyList_New(PREALLOC_SIZE(maxsplit)); list = PyList_New(PREALLOC_SIZE(maxsplit));
if (list == NULL) { if (list == NULL) {
PyObject_ReleaseBuffer(subobj, &vsub); PyBuffer_Release(&vsub);
return NULL; return NULL;
} }
@ -1196,12 +1196,12 @@ string_split(PyBytesObject *self, PyObject *args)
#endif #endif
SPLIT_ADD(s, i, len); SPLIT_ADD(s, i, len);
FIX_PREALLOC_SIZE(list); FIX_PREALLOC_SIZE(list);
PyObject_ReleaseBuffer(subobj, &vsub); PyBuffer_Release(&vsub);
return list; return list;
onError: onError:
Py_DECREF(list); Py_DECREF(list);
PyObject_ReleaseBuffer(subobj, &vsub); PyBuffer_Release(&vsub);
return NULL; return NULL;
} }
@ -1376,7 +1376,7 @@ string_rsplit(PyBytesObject *self, PyObject *args)
if (n == 0) { if (n == 0) {
PyErr_SetString(PyExc_ValueError, "empty separator"); PyErr_SetString(PyExc_ValueError, "empty separator");
PyObject_ReleaseBuffer(subobj, &vsub); PyBuffer_Release(&vsub);
return NULL; return NULL;
} }
else if (n == 1) else if (n == 1)
@ -1384,7 +1384,7 @@ string_rsplit(PyBytesObject *self, PyObject *args)
list = PyList_New(PREALLOC_SIZE(maxsplit)); list = PyList_New(PREALLOC_SIZE(maxsplit));
if (list == NULL) { if (list == NULL) {
PyObject_ReleaseBuffer(subobj, &vsub); PyBuffer_Release(&vsub);
return NULL; return NULL;
} }
@ -1406,12 +1406,12 @@ string_rsplit(PyBytesObject *self, PyObject *args)
FIX_PREALLOC_SIZE(list); FIX_PREALLOC_SIZE(list);
if (PyList_Reverse(list) < 0) if (PyList_Reverse(list) < 0)
goto onError; goto onError;
PyObject_ReleaseBuffer(subobj, &vsub); PyBuffer_Release(&vsub);
return list; return list;
onError: onError:
Py_DECREF(list); Py_DECREF(list);
PyObject_ReleaseBuffer(subobj, &vsub); PyBuffer_Release(&vsub);
return NULL; return NULL;
} }
@ -1690,7 +1690,7 @@ do_xstrip(PyBytesObject *self, int striptype, PyObject *sepobj)
j++; j++;
} }
PyObject_ReleaseBuffer(sepobj, &vsep); PyBuffer_Release(&vsep);
if (i == 0 && j == len && PyBytes_CheckExact(self)) { if (i == 0 && j == len && PyBytes_CheckExact(self)) {
Py_INCREF(self); Py_INCREF(self);
@ -2945,11 +2945,11 @@ string_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
if (PyBuffer_ToContiguous(((PyBytesObject *)new)->ob_sval, if (PyBuffer_ToContiguous(((PyBytesObject *)new)->ob_sval,
&view, view.len, 'C') < 0) &view, view.len, 'C') < 0)
goto fail; goto fail;
PyObject_ReleaseBuffer(x, &view); PyBuffer_Release(&view);
return new; return new;
fail: fail:
Py_XDECREF(new); Py_XDECREF(new);
PyObject_ReleaseBuffer(x, &view); PyBuffer_Release(&view);
return NULL; return NULL;
} }

View file

@ -6,19 +6,21 @@
static int static int
memory_getbuf(PyMemoryViewObject *self, Py_buffer *view, int flags) 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; *view = self->view;
if (self->base == NULL) }
if (self->view.obj == NULL)
return 0; 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); PyBUF_FULL);
} }
static void static void
memory_releasebuf(PyMemoryViewObject *self, Py_buffer *view) memory_releasebuf(PyMemoryViewObject *self, Py_buffer *view)
{ {
if (self->base != NULL) PyBuffer_Release(&self->view);
PyObject_ReleaseBuffer(self->base, NULL);
} }
PyDoc_STRVAR(memory_doc, PyDoc_STRVAR(memory_doc,
@ -36,6 +38,8 @@ PyMemoryView_FromMemory(Py_buffer *info)
if (mview == NULL) return NULL; if (mview == NULL) return NULL;
mview->base = NULL; mview->base = NULL;
mview->view = *info; mview->view = *info;
if (info->obj)
Py_INCREF(mview->view.obj);
return (PyObject *)mview; return (PyObject *)mview;
} }
@ -256,7 +260,7 @@ PyMemoryView_GetContiguous(PyObject *obj, int buffertype, char fort)
} }
bytes = PyByteArray_FromStringAndSize(NULL, view->len); bytes = PyByteArray_FromStringAndSize(NULL, view->len);
if (bytes == NULL) { if (bytes == NULL) {
PyObject_ReleaseBuffer(obj, view); PyBuffer_Release(view);
return NULL; return NULL;
} }
dest = PyByteArray_AS_STRING(bytes); dest = PyByteArray_AS_STRING(bytes);
@ -271,7 +275,7 @@ PyMemoryView_GetContiguous(PyObject *obj, int buffertype, char fort)
else { else {
if (_indirect_copy_nd(dest, view, fort) < 0) { if (_indirect_copy_nd(dest, view, fort) < 0) {
Py_DECREF(bytes); Py_DECREF(bytes);
PyObject_ReleaseBuffer(obj, view); PyBuffer_Release(view);
return NULL; return NULL;
} }
} }
@ -281,12 +285,12 @@ PyMemoryView_GetContiguous(PyObject *obj, int buffertype, char fort)
mem->base = PyTuple_Pack(2, obj, bytes); mem->base = PyTuple_Pack(2, obj, bytes);
Py_DECREF(bytes); Py_DECREF(bytes);
if (mem->base == NULL) { if (mem->base == NULL) {
PyObject_ReleaseBuffer(obj, view); PyBuffer_Release(view);
return NULL; return NULL;
} }
} }
else { else {
PyObject_ReleaseBuffer(obj, view); PyBuffer_Release(view);
/* steal the reference */ /* steal the reference */
mem->base = bytes; mem->base = bytes;
} }
@ -407,7 +411,7 @@ static PyMethodDef memory_methods[] = {
static void static void
memory_dealloc(PyMemoryViewObject *self) memory_dealloc(PyMemoryViewObject *self)
{ {
if (self->base != NULL) { if (self->view.obj != NULL) {
if (PyTuple_Check(self->base)) { if (PyTuple_Check(self->base)) {
/* Special case when first element is generic object /* Special case when first element is generic object
with buffer interface and the second element is a 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 be "locked" and was locked and will be unlocked
again after this call. again after this call.
*/ */
PyObject_ReleaseBuffer(PyTuple_GET_ITEM(self->base,0), PyBuffer_Release(&(self->view));
&(self->view));
} }
else { else {
PyObject_ReleaseBuffer(self->base, &(self->view)); PyBuffer_Release(&(self->view));
} }
Py_CLEAR(self->base); Py_CLEAR(self->base);
} }
@ -453,7 +456,7 @@ memory_str(PyMemoryViewObject *self)
res = PyByteArray_FromStringAndSize(NULL, view.len); res = PyByteArray_FromStringAndSize(NULL, view.len);
PyBuffer_ToContiguous(PyByteArray_AS_STRING(res), &view, view.len, 'C'); PyBuffer_ToContiguous(PyByteArray_AS_STRING(res), &view, view.len, 'C');
PyObject_ReleaseBuffer((PyObject *)self, &view); PyBuffer_Release(&view);
return res; return res;
} }
@ -466,7 +469,7 @@ memory_length(PyMemoryViewObject *self)
if (PyObject_GetBuffer((PyObject *)self, &view, PyBUF_FULL) < 0) if (PyObject_GetBuffer((PyObject *)self, &view, PyBUF_FULL) < 0)
return -1; return -1;
PyObject_ReleaseBuffer((PyObject *)self, &view); PyBuffer_Release(&view);
return view.len; return view.len;
} }

View file

@ -1198,7 +1198,7 @@ PyObject *PyUnicode_Decode(const char *s,
/* Decode via the codec registry */ /* Decode via the codec registry */
buffer = NULL; 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; goto onError;
buffer = PyMemoryView_FromMemory(&info); buffer = PyMemoryView_FromMemory(&info);
if (buffer == NULL) if (buffer == NULL)

View file

@ -814,13 +814,13 @@ Py2Reg(PyObject *value, DWORD typ, BYTE **retDataBuf, DWORD *retDataSize)
*retDataBuf = (BYTE *)PyMem_NEW(char, view.len); *retDataBuf = (BYTE *)PyMem_NEW(char, view.len);
if (*retDataBuf==NULL){ if (*retDataBuf==NULL){
PyObject_ReleaseBuffer(value, &view); PyBuffer_Release(&view);
PyErr_NoMemory(); PyErr_NoMemory();
return FALSE; return FALSE;
} }
*retDataSize = view.len; *retDataSize = view.len;
memcpy(*retDataBuf, view.buf, view.len); memcpy(*retDataBuf, view.buf, view.len);
PyObject_ReleaseBuffer(value, &view); PyBuffer_Release(&view);
} }
break; break;
} }

View file

@ -44,6 +44,7 @@ static char *converttuple(PyObject *, const char **, va_list *, int,
static char *convertsimple(PyObject *, const char **, va_list *, int, char *, static char *convertsimple(PyObject *, const char **, va_list *, int, char *,
size_t, PyObject **); size_t, PyObject **);
static Py_ssize_t convertbuffer(PyObject *, void **p, char **); static Py_ssize_t convertbuffer(PyObject *, void **p, char **);
static int getbuffer(PyObject *, Py_buffer *, char**);
static int vgetargskeywords(PyObject *, PyObject *, static int vgetargskeywords(PyObject *, PyObject *,
const char *, char **, va_list *, int); 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! */ need to be cleaned up! */
case 's': {/* text string */ 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 **); void **p = (void **)va_arg(*p_va, char **);
FETCH_SIZE; 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 */ case 'y': {/* any buffer-like object, but not PyUnicode */
void **p = (void **)va_arg(*p_va, char **); void **p = (void **)va_arg(*p_va, char **);
char *buf; 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) if (count < 0)
return converterr(buf, arg, msgbuf, bufsize); return converterr(buf, arg, msgbuf, bufsize);
if (*format == '#') { else if (*format == '#') {
FETCH_SIZE; FETCH_SIZE;
STORE_SIZE(count); STORE_SIZE(count);
format++; 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 */ 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 **); void **p = (void **)va_arg(*p_va, char **);
FETCH_SIZE; FETCH_SIZE;
@ -1189,6 +1235,26 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags,
int temp=-1; int temp=-1;
Py_buffer view; 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 || if (pb == NULL ||
pb->bf_getbuffer == NULL || pb->bf_getbuffer == NULL ||
((temp = (*pb->bf_getbuffer)(arg, &view, ((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); STORE_SIZE(count);
format++; format++;
} }
if (pb->bf_releasebuffer != NULL)
(*pb->bf_releasebuffer)(arg, &view);
break; break;
} }
@ -1237,10 +1301,11 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags,
count = view.len; count = view.len;
*p = view.buf; *p = view.buf;
/* XXX : shouldn't really release buffer, but it should be O.K. if (pb->bf_releasebuffer)
*/ return converterr(
if (pb->bf_releasebuffer != NULL) "string or pinned buffer",
(*pb->bf_releasebuffer)(arg, &view); arg, msgbuf, bufsize);
if (count < 0) if (count < 0)
return converterr("(unspecified)", arg, msgbuf, bufsize); return converterr("(unspecified)", arg, msgbuf, bufsize);
{ {
@ -1269,7 +1334,8 @@ convertbuffer(PyObject *arg, void **p, char **errmsg)
*errmsg = NULL; *errmsg = NULL;
*p = NULL; *p = NULL;
if (pb == NULL || if (pb == NULL ||
pb->bf_getbuffer == NULL) { pb->bf_getbuffer == NULL ||
pb->bf_releasebuffer != NULL) {
*errmsg = "bytes or read-only buffer"; *errmsg = "bytes or read-only buffer";
return -1; return -1;
} }
@ -1285,6 +1351,35 @@ convertbuffer(PyObject *arg, void **p, char **errmsg)
return count; 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 /* Support for keyword arguments donated by
Geoff Philbrick <philbric@delphi.hks.com> */ Geoff Philbrick <philbric@delphi.hks.com> */
@ -1624,6 +1719,8 @@ skipitem(const char **p_format, va_list *p_va, int flags)
else else
(void) va_arg(*p_va, int *); (void) va_arg(*p_va, int *);
format++; format++;
} else if ((c == 's' || c == 'z' || c == 'y') && *format == '*') {
format++;
} }
break; break;
} }

View file

@ -1168,11 +1168,14 @@ static PyObject *
marshal_loads(PyObject *self, PyObject *args) marshal_loads(PyObject *self, PyObject *args)
{ {
RFILE rf; RFILE rf;
Py_buffer p;
char *s; char *s;
Py_ssize_t n; Py_ssize_t n;
PyObject* result; PyObject* result;
if (!PyArg_ParseTuple(args, "s#:loads", &s, &n)) if (!PyArg_ParseTuple(args, "s*:loads", &p))
return NULL; return NULL;
s = p.buf;
n = p.len;
rf.fp = NULL; rf.fp = NULL;
rf.ptr = s; rf.ptr = s;
rf.end = s + n; rf.end = s + n;
@ -1180,6 +1183,7 @@ marshal_loads(PyObject *self, PyObject *args)
rf.depth = 0; rf.depth = 0;
result = read_object(&rf); result = read_object(&rf);
Py_DECREF(rf.strings); Py_DECREF(rf.strings);
PyBuffer_Release(&p);
return result; return result;
} }