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-12 14:49:50 +00:00
parent aa8efbf084
commit f91d46a17d
16 changed files with 460 additions and 273 deletions

View File

@ -40,6 +40,14 @@ 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.
.. versionadded:: 2.6
``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*.
@ -47,6 +55,10 @@ 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``.
.. versionadded:: 2.6
``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
@ -240,6 +252,10 @@ 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``.
.. versionadded:: 2.6
``(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

@ -549,24 +549,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.
@ -623,7 +605,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);
@ -633,6 +615,11 @@ 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

@ -163,6 +163,7 @@ typedef Py_ssize_t (*charbufferproc)(PyObject *, Py_ssize_t, char **);
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

@ -12,6 +12,10 @@ What's New in Python 2.6 beta 3?
Core and Builtins Core and Builtins
----------------- -----------------
- Issue #3139: Make buffer-interface thread-safe wrt. PyArg_ParseTuple,
by denying s# to parse objects that have a releasebuffer procedure,
and introducing s*.
- Issue #3537: Fix an assertion failure when an empty but presized dict - Issue #3537: Fix an assertion failure when an empty but presized dict
object was stored in the freelist. object was stored in the freelist.

View File

@ -232,20 +232,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);
@ -255,24 +255,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);
@ -282,24 +278,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);
@ -309,53 +301,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);
@ -373,24 +357,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);
@ -402,24 +382,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);
@ -429,53 +405,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);
@ -493,24 +459,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);
@ -522,83 +484,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)
@ -607,21 +574,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 */

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

@ -187,21 +187,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 +235,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

@ -792,12 +792,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, "s#:write", &buf, &len)) if (!PyArg_ParseTuple(args, "s*:write", &pbuf))
return NULL; return NULL;
buf = pbuf.buf;
len = pbuf.len;
ACQUIRE_LOCK(self); ACQUIRE_LOCK(self);
switch (self->mode) { switch (self->mode) {
@ -831,6 +834,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;
} }
@ -1549,6 +1553,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;
@ -1557,11 +1562,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, "s#:compress", &data, &datasize)) if (!PyArg_ParseTuple(args, "s*:compress", &pdata))
return NULL; return NULL;
data = pdata.buf;
datasize = pdata.len;
if (datasize == 0) if (datasize == 0) {
PyBuffer_Release(&pdata);
return PyString_FromString(""); return PyString_FromString("");
}
ACQUIRE_LOCK(self); ACQUIRE_LOCK(self);
if (!self->running) { if (!self->running) {
@ -1606,10 +1615,12 @@ BZ2Comp_compress(BZ2CompObject *self, PyObject *args)
_PyString_Resize(&ret, (Py_ssize_t)(BZS_TOTAL_OUT(bzs) - totalout)); _PyString_Resize(&ret, (Py_ssize_t)(BZS_TOTAL_OUT(bzs) - totalout));
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;
} }
@ -1833,6 +1844,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;
@ -1841,8 +1853,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, "s#:decompress", &data, &datasize)) if (!PyArg_ParseTuple(args, "s*:decompress", &pdata))
return NULL; return NULL;
data = pdata.buf;
datasize = pdata.len;
ACQUIRE_LOCK(self); ACQUIRE_LOCK(self);
if (!self->running) { if (!self->running) {
@ -1899,10 +1913,12 @@ BZ2Decomp_decompress(BZ2DecompObject *self, PyObject *args)
_PyString_Resize(&ret, (Py_ssize_t)(BZS_TOTAL_OUT(bzs) - totalout)); _PyString_Resize(&ret, (Py_ssize_t)(BZS_TOTAL_OUT(bzs) - totalout));
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;
} }
@ -2041,6 +2057,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;
@ -2050,14 +2067,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, "s#|i", if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s*|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;
} }
@ -2066,8 +2086,10 @@ bz2_compress(PyObject *self, PyObject *args, PyObject *kwargs)
bufsize = datasize + (datasize/100+1) + 600; bufsize = datasize + (datasize/100+1) + 600;
ret = PyString_FromStringAndSize(NULL, bufsize); ret = PyString_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));
@ -2079,6 +2101,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;
} }
@ -2092,6 +2115,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;
} }
@ -2099,6 +2123,7 @@ bz2_compress(PyObject *self, PyObject *args, PyObject *kwargs)
bufsize = Util_NewBufferSize(bufsize); bufsize = Util_NewBufferSize(bufsize);
if (_PyString_Resize(&ret, bufsize) < 0) { if (_PyString_Resize(&ret, bufsize) < 0) {
BZ2_bzCompressEnd(bzs); BZ2_bzCompressEnd(bzs);
PyBuffer_Release(&pdata);
Py_DECREF(ret); Py_DECREF(ret);
return NULL; return NULL;
} }
@ -2111,6 +2136,7 @@ bz2_compress(PyObject *self, PyObject *args, PyObject *kwargs)
_PyString_Resize(&ret, (Py_ssize_t)BZS_TOTAL_OUT(bzs)); _PyString_Resize(&ret, (Py_ssize_t)BZS_TOTAL_OUT(bzs));
BZ2_bzCompressEnd(bzs); BZ2_bzCompressEnd(bzs);
PyBuffer_Release(&pdata);
return ret; return ret;
} }
@ -2124,6 +2150,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;
@ -2132,15 +2159,21 @@ bz2_decompress(PyObject *self, PyObject *args)
bz_stream *bzs = &_bzs; bz_stream *bzs = &_bzs;
int bzerror; int bzerror;
if (!PyArg_ParseTuple(args, "s#:decompress", &data, &datasize)) if (!PyArg_ParseTuple(args, "s*:decompress", &pdata))
return NULL; return NULL;
data = pdata.buf;
datasize = pdata.len;
if (datasize == 0) if (datasize == 0) {
PyBuffer_Release(&pdata);
return PyString_FromString(""); return PyString_FromString("");
}
ret = PyString_FromStringAndSize(NULL, bufsize); ret = PyString_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));
@ -2153,6 +2186,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;
} }
@ -2165,6 +2199,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;
} }
@ -2172,6 +2207,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;
} }
@ -2179,6 +2215,7 @@ bz2_decompress(PyObject *self, PyObject *args)
bufsize = Util_NewBufferSize(bufsize); bufsize = Util_NewBufferSize(bufsize);
if (_PyString_Resize(&ret, bufsize) < 0) { if (_PyString_Resize(&ret, bufsize) < 0) {
BZ2_bzDecompressEnd(bzs); BZ2_bzDecompressEnd(bzs);
PyBuffer_Release(&pdata);
Py_DECREF(ret); Py_DECREF(ret);
return NULL; return NULL;
} }
@ -2190,6 +2227,7 @@ bz2_decompress(PyObject *self, PyObject *args)
if (bzs->avail_out != 0) if (bzs->avail_out != 0)
_PyString_Resize(&ret, (Py_ssize_t)BZS_TOTAL_OUT(bzs)); _PyString_Resize(&ret, (Py_ssize_t)BZS_TOTAL_OUT(bzs));
BZ2_bzDecompressEnd(bzs); BZ2_bzDecompressEnd(bzs);
PyBuffer_Release(&pdata);
return ret; return ret;
} }

View File

@ -6334,15 +6334,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 PyInt_FromSsize_t(size); return PyInt_FromSsize_t(size);

View File

@ -2647,12 +2647,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, "s#|i:send", &buf, &len, &flags)) if (!PyArg_ParseTuple(args, "s*|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);
@ -2664,6 +2669,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;
@ -2688,12 +2695,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, "s#|i:sendall", &buf, &len, &flags)) if (!PyArg_ParseTuple(args, "s*|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 {
@ -2712,6 +2724,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");
@ -2738,24 +2751,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, "s#O:sendto", &buf, &len, &addro)) { if (!PyArg_ParseTuple(args, "s*O:sendto", &pbuf, &addro)) {
PyErr_Clear(); PyErr_Clear();
if (!PyArg_ParseTuple(args, "s#iO:sendto", if (!PyArg_ParseTuple(args, "s*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);
@ -2763,6 +2784,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

@ -362,16 +362,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)
{ {
@ -603,15 +593,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;
} }
@ -621,8 +611,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;
} }
@ -632,8 +622,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++) {
@ -651,8 +641,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;
} }
@ -681,7 +671,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;
@ -692,6 +682,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;
@ -711,6 +702,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

@ -123,7 +123,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++;
} }
@ -302,9 +302,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;
} }
@ -332,7 +332,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) {
@ -340,11 +340,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;
} }
@ -555,7 +555,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;
} }
@ -841,10 +841,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;
} }
@ -1031,7 +1031,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;
} }
@ -1066,8 +1066,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;
} }
@ -1075,6 +1075,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);
} }
@ -1142,7 +1147,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;
} }
@ -1192,7 +1197,7 @@ bytes_count(PyByteArrayObject *self, PyObject *args)
count_obj = PyInt_FromSsize_t( count_obj = PyInt_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;
} }
@ -1268,7 +1273,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) {
@ -1318,7 +1323,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;
} }
@ -1498,9 +1503,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;
} }
@ -2122,7 +2127,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;
} }
@ -2130,8 +2135,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;
} }
@ -2287,7 +2292,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)
@ -2295,7 +2300,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;
} }
@ -2323,12 +2328,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;
} }
@ -2519,7 +2524,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)
@ -2527,7 +2532,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;
} }
@ -2548,12 +2553,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;
} }
@ -2828,7 +2833,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);
} }
@ -2861,7 +2866,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);
} }
@ -2894,7 +2899,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

@ -1007,6 +1007,7 @@ file_readinto(PyFileObject *f, PyObject *args)
char *ptr; char *ptr;
Py_ssize_t ntodo; Py_ssize_t ntodo;
Py_ssize_t ndone, nnow; Py_ssize_t ndone, nnow;
Py_buffer pbuf;
if (f->f_fp == NULL) if (f->f_fp == NULL)
return err_closed(); return err_closed();
@ -1015,8 +1016,10 @@ file_readinto(PyFileObject *f, PyObject *args)
(f->f_bufend - f->f_bufptr) > 0 && (f->f_bufend - f->f_bufptr) > 0 &&
f->f_buf[0] != '\0') f->f_buf[0] != '\0')
return err_iterbuffered(); return err_iterbuffered();
if (!PyArg_ParseTuple(args, "w#", &ptr, &ntodo)) if (!PyArg_ParseTuple(args, "w*", &pbuf))
return NULL; return NULL;
ptr = pbuf.buf;
ntodo = pbuf.len;
ndone = 0; ndone = 0;
while (ntodo > 0) { while (ntodo > 0) {
FILE_BEGIN_ALLOW_THREADS(f) FILE_BEGIN_ALLOW_THREADS(f)
@ -1029,11 +1032,13 @@ file_readinto(PyFileObject *f, PyObject *args)
break; break;
PyErr_SetFromErrno(PyExc_IOError); PyErr_SetFromErrno(PyExc_IOError);
clearerr(f->f_fp); clearerr(f->f_fp);
PyBuffer_Release(&pbuf);
return NULL; return NULL;
} }
ndone += nnow; ndone += nnow;
ntodo -= nnow; ntodo -= nnow;
} }
PyBuffer_Release(&pbuf);
return PyInt_FromSsize_t(ndone); return PyInt_FromSsize_t(ndone);
} }
@ -1611,17 +1616,26 @@ error:
static PyObject * static PyObject *
file_write(PyFileObject *f, PyObject *args) file_write(PyFileObject *f, PyObject *args)
{ {
Py_buffer pbuf;
char *s; char *s;
Py_ssize_t n, n2; Py_ssize_t n, n2;
if (f->f_fp == NULL) if (f->f_fp == NULL)
return err_closed(); return err_closed();
if (!PyArg_ParseTuple(args, f->f_binary ? "s#" : "t#", &s, &n)) if (f->f_binary) {
if (!PyArg_ParseTuple(args, "s*", &pbuf))
return NULL;
s = pbuf.buf;
n = pbuf.len;
} else
if (!PyArg_ParseTuple(args, "t#", &s, &n))
return NULL; return NULL;
f->f_softspace = 0; f->f_softspace = 0;
FILE_BEGIN_ALLOW_THREADS(f) FILE_BEGIN_ALLOW_THREADS(f)
errno = 0; errno = 0;
n2 = fwrite(s, 1, n, f->f_fp); n2 = fwrite(s, 1, n, f->f_fp);
FILE_END_ALLOW_THREADS(f) FILE_END_ALLOW_THREADS(f)
if (f->f_binary)
PyBuffer_Release(&pbuf);
if (n2 != n) { if (n2 != n) {
PyErr_SetFromErrno(PyExc_IOError); PyErr_SetFromErrno(PyExc_IOError);
clearerr(f->f_fp); clearerr(f->f_fp);

View File

@ -1328,7 +1328,8 @@ string_buffer_getcharbuf(PyStringObject *self, Py_ssize_t index, const char **pt
static int static int
string_buffer_getbuffer(PyStringObject *self, Py_buffer *view, int flags) string_buffer_getbuffer(PyStringObject *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);
} }
@ -1359,7 +1360,7 @@ static PyBufferProcs string_as_buffer = {
}; };
#define LEFTSTRIP 0 #define LEFTSTRIP 0
#define RIGHTSTRIP 1 #define RIGHTSTRIP 1
#define BOTHSTRIP 2 #define BOTHSTRIP 2
@ -3996,7 +3997,7 @@ PyDoc_STRVAR(p_format__doc__,
\n\ \n\
"); ");
static PyMethodDef static PyMethodDef
string_methods[] = { string_methods[] = {
/* Counterparts of the obsolete stropmodule functions; except /* Counterparts of the obsolete stropmodule functions; except

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);
@ -773,7 +774,32 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags,
} }
case 's': {/* string */ case 's': {/* string */
if (*format == '#') { if (*format == '*') {
Py_buffer *p = (Py_buffer *)va_arg(*p_va, Py_buffer *);
if (PyString_Check(arg)) {
PyBuffer_FillInfo(p, arg,
PyString_AS_STRING(arg), PyString_GET_SIZE(arg),
1, 0);
}
#ifdef Py_USING_UNICODE
else if (PyUnicode_Check(arg)) {
uarg = UNICODE_DEFAULT_ENCODING(arg);
if (uarg == NULL)
return converterr(CONV_UNICODE,
arg, msgbuf, bufsize);
PyBuffer_FillInfo(p, arg,
PyString_AS_STRING(uarg), PyString_GET_SIZE(uarg),
1, 0);
}
#endif
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;
@ -823,7 +849,34 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags,
} }
case 'z': {/* string, may be NULL (None) */ case 'z': {/* string, may be NULL (None) */
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 (PyString_Check(arg)) {
PyBuffer_FillInfo(p, arg,
PyString_AS_STRING(arg), PyString_GET_SIZE(arg),
1, 0);
}
#ifdef Py_USING_UNICODE
else if (PyUnicode_Check(arg)) {
uarg = UNICODE_DEFAULT_ENCODING(arg);
if (uarg == NULL)
return converterr(CONV_UNICODE,
arg, msgbuf, bufsize);
PyBuffer_FillInfo(p, arg,
PyString_AS_STRING(uarg), PyString_GET_SIZE(uarg),
1, 0);
}
#endif
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;
@ -1144,9 +1197,28 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags,
case 'w': { /* memory buffer, read-write access */ case 'w': { /* memory buffer, read-write access */
void **p = va_arg(*p_va, void **); void **p = va_arg(*p_va, void **);
void *res;
PyBufferProcs *pb = arg->ob_type->tp_as_buffer; PyBufferProcs *pb = arg->ob_type->tp_as_buffer;
Py_ssize_t count; Py_ssize_t count;
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;
}
if (pb == NULL || if (pb == NULL ||
pb->bf_getwritebuffer == NULL || pb->bf_getwritebuffer == NULL ||
pb->bf_getsegcount == NULL) pb->bf_getsegcount == NULL)
@ -1154,13 +1226,20 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags,
if ((*pb->bf_getsegcount)(arg, NULL) != 1) if ((*pb->bf_getsegcount)(arg, NULL) != 1)
return converterr("single-segment read-write buffer", return converterr("single-segment read-write buffer",
arg, msgbuf, bufsize); arg, msgbuf, bufsize);
if ((count = pb->bf_getwritebuffer(arg, 0, p)) < 0) if ((count = pb->bf_getwritebuffer(arg, 0, &res)) < 0)
return converterr("(unspecified)", arg, msgbuf, bufsize); return converterr("(unspecified)", arg, msgbuf, bufsize);
if (*format == '*') {
PyBuffer_FillInfo((Py_buffer*)p, arg, res, count, 1, 0);
format++;
}
else {
*p = res;
if (*format == '#') { if (*format == '#') {
FETCH_SIZE; FETCH_SIZE;
STORE_SIZE(count); STORE_SIZE(count);
format++; format++;
} }
}
break; break;
} }
@ -1186,6 +1265,11 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags,
"string or single-segment read-only buffer", "string or single-segment read-only buffer",
arg, msgbuf, bufsize); arg, msgbuf, bufsize);
if (pb->bf_releasebuffer)
return converterr(
"string or pinned buffer",
arg, msgbuf, bufsize);
count = pb->bf_getcharbuffer(arg, 0, p); count = pb->bf_getcharbuffer(arg, 0, p);
if (count < 0) if (count < 0)
return converterr("(unspecified)", arg, msgbuf, bufsize); return converterr("(unspecified)", arg, msgbuf, bufsize);
@ -1212,7 +1296,8 @@ convertbuffer(PyObject *arg, void **p, char **errmsg)
Py_ssize_t count; Py_ssize_t count;
if (pb == NULL || if (pb == NULL ||
pb->bf_getreadbuffer == NULL || pb->bf_getreadbuffer == NULL ||
pb->bf_getsegcount == NULL) { pb->bf_getsegcount == NULL ||
pb->bf_releasebuffer != NULL) {
*errmsg = "string or read-only buffer"; *errmsg = "string or read-only buffer";
return -1; return -1;
} }
@ -1226,6 +1311,33 @@ convertbuffer(PyObject *arg, void **p, char **errmsg)
return count; return count;
} }
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> */
@ -1566,6 +1678,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') && *format == '*') {
format++;
} }
break; break;
} }