bpo-40943: PY_SSIZE_T_CLEAN required for '#' formats (GH-20784)
The PY_SSIZE_T_CLEAN macro must now be defined to use PyArg_ParseTuple() and Py_BuildValue() "#" formats: "es#", "et#", "s#", "u#", "y#", "z#", "U#" and "Z#". See the PEP 353. Update _testcapi.test_buildvalue_issue38913().
This commit is contained in:
parent
01ece63d42
commit
37bb289556
|
@ -55,13 +55,11 @@ which disallows mutable objects such as :class:`bytearray`.
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
For all ``#`` variants of formats (``s#``, ``y#``, etc.), the type of
|
For all ``#`` variants of formats (``s#``, ``y#``, etc.), the macro
|
||||||
the length argument (int or :c:type:`Py_ssize_t`) is controlled by
|
:c:macro:`PY_SSIZE_T_CLEAN` must be defined before including
|
||||||
defining the macro :c:macro:`PY_SSIZE_T_CLEAN` before including
|
:file:`Python.h`. On Python 3.9 and older, the type of the length argument
|
||||||
:file:`Python.h`. If the macro was defined, length is a
|
is :c:type:`Py_ssize_t` if the :c:macro:`PY_SSIZE_T_CLEAN` macro is defined,
|
||||||
:c:type:`Py_ssize_t` rather than an :c:type:`int`. This behavior will change
|
or int otherwise.
|
||||||
in a future Python version to only support :c:type:`Py_ssize_t` and
|
|
||||||
drop :c:type:`int` support. It is best to always define :c:macro:`PY_SSIZE_T_CLEAN`.
|
|
||||||
|
|
||||||
|
|
||||||
``s`` (:class:`str`) [const char \*]
|
``s`` (:class:`str`) [const char \*]
|
||||||
|
@ -90,7 +88,7 @@ which disallows mutable objects such as :class:`bytearray`.
|
||||||
In this case the resulting C string may contain embedded NUL bytes.
|
In this case the resulting C string may contain embedded NUL bytes.
|
||||||
Unicode objects are converted to C strings using ``'utf-8'`` encoding.
|
Unicode objects are converted to C strings using ``'utf-8'`` encoding.
|
||||||
|
|
||||||
``s#`` (:class:`str`, read-only :term:`bytes-like object`) [const char \*, int or :c:type:`Py_ssize_t`]
|
``s#`` (:class:`str`, read-only :term:`bytes-like object`) [const char \*, :c:type:`Py_ssize_t`]
|
||||||
Like ``s*``, except that it doesn't accept mutable objects.
|
Like ``s*``, except that it doesn't accept mutable objects.
|
||||||
The result is stored into two C variables,
|
The result is stored into two C variables,
|
||||||
the first one a pointer to a C string, the second one its length.
|
the first one a pointer to a C string, the second one its length.
|
||||||
|
@ -105,7 +103,7 @@ which disallows mutable objects such as :class:`bytearray`.
|
||||||
Like ``s*``, but the Python object may also be ``None``, in which case the
|
Like ``s*``, but the Python object may also be ``None``, in which case the
|
||||||
``buf`` member of the :c:type:`Py_buffer` structure is set to ``NULL``.
|
``buf`` member of the :c:type:`Py_buffer` structure is set to ``NULL``.
|
||||||
|
|
||||||
``z#`` (:class:`str`, read-only :term:`bytes-like object` or ``None``) [const char \*, int or :c:type:`Py_ssize_t`]
|
``z#`` (:class:`str`, read-only :term:`bytes-like object` or ``None``) [const char \*, :c:type:`Py_ssize_t`]
|
||||||
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``.
|
||||||
|
|
||||||
|
@ -124,7 +122,7 @@ which disallows mutable objects such as :class:`bytearray`.
|
||||||
bytes-like objects. **This is the recommended way to accept
|
bytes-like objects. **This is the recommended way to accept
|
||||||
binary data.**
|
binary data.**
|
||||||
|
|
||||||
``y#`` (read-only :term:`bytes-like object`) [const char \*, int or :c:type:`Py_ssize_t`]
|
``y#`` (read-only :term:`bytes-like object`) [const char \*, :c:type:`Py_ssize_t`]
|
||||||
This variant on ``s#`` doesn't accept Unicode objects, only bytes-like
|
This variant on ``s#`` doesn't accept Unicode objects, only bytes-like
|
||||||
objects.
|
objects.
|
||||||
|
|
||||||
|
@ -155,7 +153,7 @@ which disallows mutable objects such as :class:`bytearray`.
|
||||||
Part of the old-style :c:type:`Py_UNICODE` API; please migrate to using
|
Part of the old-style :c:type:`Py_UNICODE` API; please migrate to using
|
||||||
:c:func:`PyUnicode_AsWideCharString`.
|
:c:func:`PyUnicode_AsWideCharString`.
|
||||||
|
|
||||||
``u#`` (:class:`str`) [const Py_UNICODE \*, int or :c:type:`Py_ssize_t`]
|
``u#`` (:class:`str`) [const Py_UNICODE \*, :c:type:`Py_ssize_t`]
|
||||||
This variant on ``u`` stores into two C variables, the first one a pointer to a
|
This variant on ``u`` stores into two C variables, the first one a pointer to a
|
||||||
Unicode data buffer, the second one its length. This variant allows
|
Unicode data buffer, the second one its length. This variant allows
|
||||||
null code points.
|
null code points.
|
||||||
|
@ -172,7 +170,7 @@ which disallows mutable objects such as :class:`bytearray`.
|
||||||
Part of the old-style :c:type:`Py_UNICODE` API; please migrate to using
|
Part of the old-style :c:type:`Py_UNICODE` API; please migrate to using
|
||||||
:c:func:`PyUnicode_AsWideCharString`.
|
:c:func:`PyUnicode_AsWideCharString`.
|
||||||
|
|
||||||
``Z#`` (:class:`str` or ``None``) [const Py_UNICODE \*, int or :c:type:`Py_ssize_t`]
|
``Z#`` (:class:`str` or ``None``) [const Py_UNICODE \*, :c:type:`Py_ssize_t`]
|
||||||
Like ``u#``, but the Python object may also be ``None``, in which case the
|
Like ``u#``, but the Python object may also be ``None``, in which case the
|
||||||
:c:type:`Py_UNICODE` pointer is set to ``NULL``.
|
:c:type:`Py_UNICODE` pointer is set to ``NULL``.
|
||||||
|
|
||||||
|
@ -213,7 +211,7 @@ which disallows mutable objects such as :class:`bytearray`.
|
||||||
recoding them. Instead, the implementation assumes that the byte string object uses
|
recoding them. Instead, the implementation assumes that the byte string object uses
|
||||||
the encoding passed in as parameter.
|
the encoding passed in as parameter.
|
||||||
|
|
||||||
``es#`` (:class:`str`) [const char \*encoding, char \*\*buffer, int or :c:type:`Py_ssize_t` \*buffer_length]
|
``es#`` (:class:`str`) [const char \*encoding, char \*\*buffer, :c:type:`Py_ssize_t` \*buffer_length]
|
||||||
This variant on ``s#`` is used for encoding Unicode into a character buffer.
|
This variant on ``s#`` is used for encoding Unicode into a character buffer.
|
||||||
Unlike the ``es`` format, this variant allows input data which contains NUL
|
Unlike the ``es`` format, this variant allows input data which contains NUL
|
||||||
characters.
|
characters.
|
||||||
|
@ -244,7 +242,7 @@ which disallows mutable objects such as :class:`bytearray`.
|
||||||
In both cases, *\*buffer_length* is set to the length of the encoded data
|
In both cases, *\*buffer_length* is set to the length of the encoded data
|
||||||
without the trailing NUL byte.
|
without the trailing NUL byte.
|
||||||
|
|
||||||
``et#`` (:class:`str`, :class:`bytes` or :class:`bytearray`) [const char \*encoding, char \*\*buffer, int or :c:type:`Py_ssize_t` \*buffer_length]
|
``et#`` (:class:`str`, :class:`bytes` or :class:`bytearray`) [const char \*encoding, char \*\*buffer, :c:type:`Py_ssize_t` \*buffer_length]
|
||||||
Same as ``es#`` except that byte string objects are passed through without recoding
|
Same as ``es#`` except that byte string objects are passed through without recoding
|
||||||
them. Instead, the implementation assumes that the byte string object uses the
|
them. Instead, the implementation assumes that the byte string object uses the
|
||||||
encoding passed in as parameter.
|
encoding passed in as parameter.
|
||||||
|
@ -549,7 +547,7 @@ Building values
|
||||||
Convert a null-terminated C string to a Python :class:`str` object using ``'utf-8'``
|
Convert a null-terminated C string to a Python :class:`str` object using ``'utf-8'``
|
||||||
encoding. If the C string pointer is ``NULL``, ``None`` is used.
|
encoding. If the C string pointer is ``NULL``, ``None`` is used.
|
||||||
|
|
||||||
``s#`` (:class:`str` or ``None``) [const char \*, int or :c:type:`Py_ssize_t`]
|
``s#`` (:class:`str` or ``None``) [const char \*, :c:type:`Py_ssize_t`]
|
||||||
Convert a C string and its length to a Python :class:`str` object using ``'utf-8'``
|
Convert a C string and its length to a Python :class:`str` object using ``'utf-8'``
|
||||||
encoding. If the C string pointer is ``NULL``, the length is ignored and
|
encoding. If the C string pointer is ``NULL``, the length is ignored and
|
||||||
``None`` is returned.
|
``None`` is returned.
|
||||||
|
@ -558,14 +556,14 @@ Building values
|
||||||
This converts a C string to a Python :class:`bytes` object. If the C
|
This converts a C string to a Python :class:`bytes` object. If the C
|
||||||
string pointer is ``NULL``, ``None`` is returned.
|
string pointer is ``NULL``, ``None`` is returned.
|
||||||
|
|
||||||
``y#`` (:class:`bytes`) [const char \*, int or :c:type:`Py_ssize_t`]
|
``y#`` (:class:`bytes`) [const char \*, :c:type:`Py_ssize_t`]
|
||||||
This converts a C string and its lengths to a Python object. If the C
|
This converts a C string and its lengths to a Python object. If the C
|
||||||
string pointer is ``NULL``, ``None`` is returned.
|
string pointer is ``NULL``, ``None`` is returned.
|
||||||
|
|
||||||
``z`` (:class:`str` or ``None``) [const char \*]
|
``z`` (:class:`str` or ``None``) [const char \*]
|
||||||
Same as ``s``.
|
Same as ``s``.
|
||||||
|
|
||||||
``z#`` (:class:`str` or ``None``) [const char \*, int or :c:type:`Py_ssize_t`]
|
``z#`` (:class:`str` or ``None``) [const char \*, :c:type:`Py_ssize_t`]
|
||||||
Same as ``s#``.
|
Same as ``s#``.
|
||||||
|
|
||||||
``u`` (:class:`str`) [const wchar_t \*]
|
``u`` (:class:`str`) [const wchar_t \*]
|
||||||
|
@ -573,7 +571,7 @@ Building values
|
||||||
data to a Python Unicode object. If the Unicode buffer pointer is ``NULL``,
|
data to a Python Unicode object. If the Unicode buffer pointer is ``NULL``,
|
||||||
``None`` is returned.
|
``None`` is returned.
|
||||||
|
|
||||||
``u#`` (:class:`str`) [const wchar_t \*, int or :c:type:`Py_ssize_t`]
|
``u#`` (:class:`str`) [const wchar_t \*, :c:type:`Py_ssize_t`]
|
||||||
Convert a Unicode (UTF-16 or UCS-4) data buffer and its length to a Python
|
Convert a Unicode (UTF-16 or UCS-4) data buffer and its length to a Python
|
||||||
Unicode object. If the Unicode buffer pointer is ``NULL``, the length is ignored
|
Unicode object. If the Unicode buffer pointer is ``NULL``, the length is ignored
|
||||||
and ``None`` is returned.
|
and ``None`` is returned.
|
||||||
|
@ -581,7 +579,7 @@ Building values
|
||||||
``U`` (:class:`str` or ``None``) [const char \*]
|
``U`` (:class:`str` or ``None``) [const char \*]
|
||||||
Same as ``s``.
|
Same as ``s``.
|
||||||
|
|
||||||
``U#`` (:class:`str` or ``None``) [const char \*, int or :c:type:`Py_ssize_t`]
|
``U#`` (:class:`str` or ``None``) [const char \*, :c:type:`Py_ssize_t`]
|
||||||
Same as ``s#``.
|
Same as ``s#``.
|
||||||
|
|
||||||
``i`` (:class:`int`) [int]
|
``i`` (:class:`int`) [int]
|
||||||
|
|
|
@ -155,6 +155,13 @@ New Features
|
||||||
Porting to Python 3.10
|
Porting to Python 3.10
|
||||||
----------------------
|
----------------------
|
||||||
|
|
||||||
|
* The ``PY_SSIZE_T_CLEAN`` macro must now be defined to use
|
||||||
|
:c:func:`PyArg_ParseTuple` and :c:func:`Py_BuildValue` formats which use
|
||||||
|
``#``: ``es#``, ``et#``, ``s#``, ``u#``, ``y#``, ``z#``, ``U#`` and ``Z#``.
|
||||||
|
See :ref:`Parsing arguments and building values
|
||||||
|
<arg-parsing>` and the :pep:`353`.
|
||||||
|
(Contributed by Victor Stinner in :issue:`40943`.)
|
||||||
|
|
||||||
* Since :c:func:`Py_TYPE()` is changed to the inline static function,
|
* Since :c:func:`Py_TYPE()` is changed to the inline static function,
|
||||||
``Py_TYPE(obj) = new_type`` must be replaced with ``Py_SET_TYPE(obj, new_type)``:
|
``Py_TYPE(obj) = new_type`` must be replaced with ``Py_SET_TYPE(obj, new_type)``:
|
||||||
see :c:func:`Py_SET_TYPE()` (available since Python 3.9). For backward
|
see :c:func:`Py_SET_TYPE()` (available since Python 3.9). For backward
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
The ``PY_SSIZE_T_CLEAN`` macro must now be defined to use
|
||||||
|
:c:func:`PyArg_ParseTuple` and :c:func:`Py_BuildValue` formats which use ``#``:
|
||||||
|
``es#``, ``et#``, ``s#``, ``u#``, ``y#``, ``z#``, ``U#`` and ``Z#``.
|
||||||
|
See :ref:`Parsing arguments and building values <arg-parsing>` and the
|
||||||
|
:pep:`353`.
|
|
@ -6868,29 +6868,36 @@ test_buildvalue_issue38913(PyObject *self, PyObject *Py_UNUSED(ignored))
|
||||||
PyObject *res;
|
PyObject *res;
|
||||||
const char str[] = "string";
|
const char str[] = "string";
|
||||||
const Py_UNICODE unicode[] = L"unicode";
|
const Py_UNICODE unicode[] = L"unicode";
|
||||||
PyErr_SetNone(PyExc_ZeroDivisionError);
|
assert(!PyErr_Occurred());
|
||||||
|
|
||||||
res = Py_BuildValue("(s#O)", str, 1, Py_None);
|
res = Py_BuildValue("(s#O)", str, 1, Py_None);
|
||||||
assert(res == NULL);
|
assert(res == NULL);
|
||||||
if (!PyErr_ExceptionMatches(PyExc_ZeroDivisionError)) {
|
if (!PyErr_ExceptionMatches(PyExc_SystemError)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
PyErr_Clear();
|
||||||
|
|
||||||
res = Py_BuildValue("(z#O)", str, 1, Py_None);
|
res = Py_BuildValue("(z#O)", str, 1, Py_None);
|
||||||
assert(res == NULL);
|
assert(res == NULL);
|
||||||
if (!PyErr_ExceptionMatches(PyExc_ZeroDivisionError)) {
|
if (!PyErr_ExceptionMatches(PyExc_SystemError)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
PyErr_Clear();
|
||||||
|
|
||||||
res = Py_BuildValue("(y#O)", str, 1, Py_None);
|
res = Py_BuildValue("(y#O)", str, 1, Py_None);
|
||||||
assert(res == NULL);
|
assert(res == NULL);
|
||||||
if (!PyErr_ExceptionMatches(PyExc_ZeroDivisionError)) {
|
if (!PyErr_ExceptionMatches(PyExc_SystemError)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
PyErr_Clear();
|
||||||
|
|
||||||
res = Py_BuildValue("(u#O)", unicode, 1, Py_None);
|
res = Py_BuildValue("(u#O)", unicode, 1, Py_None);
|
||||||
assert(res == NULL);
|
assert(res == NULL);
|
||||||
if (!PyErr_ExceptionMatches(PyExc_ZeroDivisionError)) {
|
if (!PyErr_ExceptionMatches(PyExc_SystemError)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
PyErr_Clear();
|
PyErr_Clear();
|
||||||
|
|
||||||
|
|
||||||
Py_RETURN_NONE;
|
Py_RETURN_NONE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -656,27 +656,12 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags,
|
||||||
char *msgbuf, size_t bufsize, freelist_t *freelist)
|
char *msgbuf, size_t bufsize, freelist_t *freelist)
|
||||||
{
|
{
|
||||||
/* For # codes */
|
/* For # codes */
|
||||||
#define FETCH_SIZE int *q=NULL;Py_ssize_t *q2=NULL;\
|
#define REQUIRE_PY_SSIZE_T_CLEAN \
|
||||||
if (flags & FLAG_SIZE_T) q2=va_arg(*p_va, Py_ssize_t*); \
|
if (!(flags & FLAG_SIZE_T)) { \
|
||||||
else { \
|
PyErr_SetString(PyExc_SystemError, \
|
||||||
if (PyErr_WarnEx(PyExc_DeprecationWarning, \
|
"PY_SSIZE_T_CLEAN macro must be defined for '#' formats"); \
|
||||||
"PY_SSIZE_T_CLEAN will be required for '#' formats", 1)) { \
|
|
||||||
return NULL; \
|
return NULL; \
|
||||||
} \
|
|
||||||
q=va_arg(*p_va, int*); \
|
|
||||||
}
|
}
|
||||||
#define STORE_SIZE(s) \
|
|
||||||
if (flags & FLAG_SIZE_T) \
|
|
||||||
*q2=s; \
|
|
||||||
else { \
|
|
||||||
if (INT_MAX < s) { \
|
|
||||||
PyErr_SetString(PyExc_OverflowError, \
|
|
||||||
"size does not fit in an int"); \
|
|
||||||
return converterr("", arg, msgbuf, bufsize); \
|
|
||||||
} \
|
|
||||||
*q = (int)s; \
|
|
||||||
}
|
|
||||||
#define BUFFER_LEN ((flags & FLAG_SIZE_T) ? *q2:*q)
|
|
||||||
#define RETURN_ERR_OCCURRED return msgbuf
|
#define RETURN_ERR_OCCURRED return msgbuf
|
||||||
|
|
||||||
const char *format = *p_format;
|
const char *format = *p_format;
|
||||||
|
@ -931,8 +916,9 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags,
|
||||||
if (count < 0)
|
if (count < 0)
|
||||||
return converterr(buf, arg, msgbuf, bufsize);
|
return converterr(buf, arg, msgbuf, bufsize);
|
||||||
if (*format == '#') {
|
if (*format == '#') {
|
||||||
FETCH_SIZE;
|
REQUIRE_PY_SSIZE_T_CLEAN;
|
||||||
STORE_SIZE(count);
|
Py_ssize_t *psize = va_arg(*p_va, Py_ssize_t*);
|
||||||
|
*psize = count;
|
||||||
format++;
|
format++;
|
||||||
} else {
|
} else {
|
||||||
if (strlen(*p) != (size_t)count) {
|
if (strlen(*p) != (size_t)count) {
|
||||||
|
@ -974,11 +960,12 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags,
|
||||||
} else if (*format == '#') { /* a string or read-only bytes-like object */
|
} else if (*format == '#') { /* a string or read-only bytes-like object */
|
||||||
/* "s#" or "z#" */
|
/* "s#" or "z#" */
|
||||||
const void **p = (const void **)va_arg(*p_va, const char **);
|
const void **p = (const void **)va_arg(*p_va, const char **);
|
||||||
FETCH_SIZE;
|
REQUIRE_PY_SSIZE_T_CLEAN;
|
||||||
|
Py_ssize_t *psize = va_arg(*p_va, Py_ssize_t*);
|
||||||
|
|
||||||
if (c == 'z' && arg == Py_None) {
|
if (c == 'z' && arg == Py_None) {
|
||||||
*p = NULL;
|
*p = NULL;
|
||||||
STORE_SIZE(0);
|
*psize = 0;
|
||||||
}
|
}
|
||||||
else if (PyUnicode_Check(arg)) {
|
else if (PyUnicode_Check(arg)) {
|
||||||
Py_ssize_t len;
|
Py_ssize_t len;
|
||||||
|
@ -987,7 +974,7 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags,
|
||||||
return converterr(CONV_UNICODE,
|
return converterr(CONV_UNICODE,
|
||||||
arg, msgbuf, bufsize);
|
arg, msgbuf, bufsize);
|
||||||
*p = sarg;
|
*p = sarg;
|
||||||
STORE_SIZE(len);
|
*psize = len;
|
||||||
}
|
}
|
||||||
else { /* read-only bytes-like object */
|
else { /* read-only bytes-like object */
|
||||||
/* XXX Really? */
|
/* XXX Really? */
|
||||||
|
@ -995,7 +982,7 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags,
|
||||||
Py_ssize_t count = convertbuffer(arg, p, &buf);
|
Py_ssize_t count = convertbuffer(arg, p, &buf);
|
||||||
if (count < 0)
|
if (count < 0)
|
||||||
return converterr(buf, arg, msgbuf, bufsize);
|
return converterr(buf, arg, msgbuf, bufsize);
|
||||||
STORE_SIZE(count);
|
*psize = count;
|
||||||
}
|
}
|
||||||
format++;
|
format++;
|
||||||
} else {
|
} else {
|
||||||
|
@ -1034,18 +1021,19 @@ _Py_COMP_DIAG_IGNORE_DEPR_DECLS
|
||||||
|
|
||||||
if (*format == '#') {
|
if (*format == '#') {
|
||||||
/* "u#" or "Z#" */
|
/* "u#" or "Z#" */
|
||||||
FETCH_SIZE;
|
REQUIRE_PY_SSIZE_T_CLEAN;
|
||||||
|
Py_ssize_t *psize = va_arg(*p_va, Py_ssize_t*);
|
||||||
|
|
||||||
if (c == 'Z' && arg == Py_None) {
|
if (c == 'Z' && arg == Py_None) {
|
||||||
*p = NULL;
|
*p = NULL;
|
||||||
STORE_SIZE(0);
|
*psize = 0;
|
||||||
}
|
}
|
||||||
else if (PyUnicode_Check(arg)) {
|
else if (PyUnicode_Check(arg)) {
|
||||||
Py_ssize_t len;
|
Py_ssize_t len;
|
||||||
*p = PyUnicode_AsUnicodeAndSize(arg, &len);
|
*p = PyUnicode_AsUnicodeAndSize(arg, &len);
|
||||||
if (*p == NULL)
|
if (*p == NULL)
|
||||||
RETURN_ERR_OCCURRED;
|
RETURN_ERR_OCCURRED;
|
||||||
STORE_SIZE(len);
|
*psize = len;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return converterr(c == 'Z' ? "str or None" : "str",
|
return converterr(c == 'Z' ? "str or None" : "str",
|
||||||
|
@ -1160,22 +1148,11 @@ _Py_COMP_DIAG_POP
|
||||||
trailing 0-byte
|
trailing 0-byte
|
||||||
|
|
||||||
*/
|
*/
|
||||||
int *q = NULL; Py_ssize_t *q2 = NULL;
|
REQUIRE_PY_SSIZE_T_CLEAN;
|
||||||
if (flags & FLAG_SIZE_T) {
|
Py_ssize_t *psize = va_arg(*p_va, Py_ssize_t*);
|
||||||
q2 = va_arg(*p_va, Py_ssize_t*);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (PyErr_WarnEx(PyExc_DeprecationWarning,
|
|
||||||
"PY_SSIZE_T_CLEAN will be required for '#' formats", 1))
|
|
||||||
{
|
|
||||||
Py_DECREF(s);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
q = va_arg(*p_va, int*);
|
|
||||||
}
|
|
||||||
|
|
||||||
format++;
|
format++;
|
||||||
if (q == NULL && q2 == NULL) {
|
if (psize == NULL) {
|
||||||
Py_DECREF(s);
|
Py_DECREF(s);
|
||||||
return converterr(
|
return converterr(
|
||||||
"(buffer_len is NULL)",
|
"(buffer_len is NULL)",
|
||||||
|
@ -1195,30 +1172,20 @@ _Py_COMP_DIAG_POP
|
||||||
arg, msgbuf, bufsize);
|
arg, msgbuf, bufsize);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (size + 1 > BUFFER_LEN) {
|
if (size + 1 > *psize) {
|
||||||
Py_DECREF(s);
|
Py_DECREF(s);
|
||||||
PyErr_Format(PyExc_ValueError,
|
PyErr_Format(PyExc_ValueError,
|
||||||
"encoded string too long "
|
"encoded string too long "
|
||||||
"(%zd, maximum length %zd)",
|
"(%zd, maximum length %zd)",
|
||||||
(Py_ssize_t)size, (Py_ssize_t)(BUFFER_LEN-1));
|
(Py_ssize_t)size, (Py_ssize_t)(*psize - 1));
|
||||||
RETURN_ERR_OCCURRED;
|
RETURN_ERR_OCCURRED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
memcpy(*buffer, ptr, size+1);
|
memcpy(*buffer, ptr, size+1);
|
||||||
|
|
||||||
if (flags & FLAG_SIZE_T) {
|
*psize = size;
|
||||||
*q2 = size;
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (INT_MAX < size) {
|
|
||||||
Py_DECREF(s);
|
|
||||||
PyErr_SetString(PyExc_OverflowError,
|
|
||||||
"size does not fit in an int");
|
|
||||||
return converterr("", arg, msgbuf, bufsize);
|
|
||||||
}
|
|
||||||
*q = (int)size;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
/* Using a 0-terminated buffer:
|
/* Using a 0-terminated buffer:
|
||||||
|
|
||||||
- the encoded string has to be 0-terminated
|
- the encoded string has to be 0-terminated
|
||||||
|
@ -1356,9 +1323,7 @@ _Py_COMP_DIAG_POP
|
||||||
*p_format = format;
|
*p_format = format;
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
#undef FETCH_SIZE
|
#undef REQUIRE_PY_SSIZE_T_CLEAN
|
||||||
#undef STORE_SIZE
|
|
||||||
#undef BUFFER_LEN
|
|
||||||
#undef RETURN_ERR_OCCURRED
|
#undef RETURN_ERR_OCCURRED
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -283,6 +283,13 @@ do_mktuple(const char **p_format, va_list *p_va, char endchar, Py_ssize_t n, int
|
||||||
static PyObject *
|
static PyObject *
|
||||||
do_mkvalue(const char **p_format, va_list *p_va, int flags)
|
do_mkvalue(const char **p_format, va_list *p_va, int flags)
|
||||||
{
|
{
|
||||||
|
#define ERROR_NEED_PY_SSIZE_T_CLEAN \
|
||||||
|
{ \
|
||||||
|
PyErr_SetString(PyExc_SystemError, \
|
||||||
|
"PY_SSIZE_T_CLEAN macro must be defined for '#' formats"); \
|
||||||
|
return NULL; \
|
||||||
|
}
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
switch (*(*p_format)++) {
|
switch (*(*p_format)++) {
|
||||||
case '(':
|
case '(':
|
||||||
|
@ -341,14 +348,12 @@ do_mkvalue(const char **p_format, va_list *p_va, int flags)
|
||||||
Py_ssize_t n;
|
Py_ssize_t n;
|
||||||
if (**p_format == '#') {
|
if (**p_format == '#') {
|
||||||
++*p_format;
|
++*p_format;
|
||||||
if (flags & FLAG_SIZE_T)
|
if (flags & FLAG_SIZE_T) {
|
||||||
n = va_arg(*p_va, Py_ssize_t);
|
n = va_arg(*p_va, Py_ssize_t);
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
n = va_arg(*p_va, int);
|
n = va_arg(*p_va, int);
|
||||||
if (PyErr_WarnEx(PyExc_DeprecationWarning,
|
ERROR_NEED_PY_SSIZE_T_CLEAN;
|
||||||
"PY_SSIZE_T_CLEAN will be required for '#' formats", 1)) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -394,14 +399,12 @@ do_mkvalue(const char **p_format, va_list *p_va, int flags)
|
||||||
Py_ssize_t n;
|
Py_ssize_t n;
|
||||||
if (**p_format == '#') {
|
if (**p_format == '#') {
|
||||||
++*p_format;
|
++*p_format;
|
||||||
if (flags & FLAG_SIZE_T)
|
if (flags & FLAG_SIZE_T) {
|
||||||
n = va_arg(*p_va, Py_ssize_t);
|
n = va_arg(*p_va, Py_ssize_t);
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
n = va_arg(*p_va, int);
|
n = va_arg(*p_va, int);
|
||||||
if (PyErr_WarnEx(PyExc_DeprecationWarning,
|
ERROR_NEED_PY_SSIZE_T_CLEAN;
|
||||||
"PY_SSIZE_T_CLEAN will be required for '#' formats", 1)) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -432,14 +435,12 @@ do_mkvalue(const char **p_format, va_list *p_va, int flags)
|
||||||
Py_ssize_t n;
|
Py_ssize_t n;
|
||||||
if (**p_format == '#') {
|
if (**p_format == '#') {
|
||||||
++*p_format;
|
++*p_format;
|
||||||
if (flags & FLAG_SIZE_T)
|
if (flags & FLAG_SIZE_T) {
|
||||||
n = va_arg(*p_va, Py_ssize_t);
|
n = va_arg(*p_va, Py_ssize_t);
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
n = va_arg(*p_va, int);
|
n = va_arg(*p_va, int);
|
||||||
if (PyErr_WarnEx(PyExc_DeprecationWarning,
|
ERROR_NEED_PY_SSIZE_T_CLEAN;
|
||||||
"PY_SSIZE_T_CLEAN will be required for '#' formats", 1)) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -507,6 +508,8 @@ do_mkvalue(const char **p_format, va_list *p_va, int flags)
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#undef ERROR_NEED_PY_SSIZE_T_CLEAN
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue