bpo-30708: Check for null characters in PyUnicode_AsWideCharString(). (#2285)
Raise a ValueError if the second argument is NULL and the wchar_t\* string contains null characters.
This commit is contained in:
parent
65474b9d7a
commit
e613e6add5
|
@ -934,16 +934,22 @@ wchar_t Support
|
||||||
Convert the Unicode object to a wide character string. The output string
|
Convert the Unicode object to a wide character string. The output string
|
||||||
always ends with a null character. If *size* is not *NULL*, write the number
|
always ends with a null character. If *size* is not *NULL*, write the number
|
||||||
of wide characters (excluding the trailing null termination character) into
|
of wide characters (excluding the trailing null termination character) into
|
||||||
*\*size*.
|
*\*size*. Note that the resulting :c:type:`wchar_t` string might contain
|
||||||
|
null characters, which would cause the string to be truncated when used with
|
||||||
|
most C functions. If *size* is *NULL* and the :c:type:`wchar_t*` string
|
||||||
|
contains null characters a :exc:`ValueError` is raised.
|
||||||
|
|
||||||
Returns a buffer allocated by :c:func:`PyMem_Alloc` (use
|
Returns a buffer allocated by :c:func:`PyMem_Alloc` (use
|
||||||
:c:func:`PyMem_Free` to free it) on success. On error, returns *NULL*,
|
:c:func:`PyMem_Free` to free it) on success. On error, returns *NULL*
|
||||||
*\*size* is undefined and raises a :exc:`MemoryError`. Note that the
|
and *\*size* is undefined. Raises a :exc:`MemoryError` if memory allocation
|
||||||
resulting :c:type:`wchar_t` string might contain null characters, which
|
is failed.
|
||||||
would cause the string to be truncated when used with most C functions.
|
|
||||||
|
|
||||||
.. versionadded:: 3.2
|
.. versionadded:: 3.2
|
||||||
|
|
||||||
|
.. versionchanged:: 3.7
|
||||||
|
Raises a :exc:`ValueError` if *size* is *NULL* and the :c:type:`wchar_t*`
|
||||||
|
string contains null characters.
|
||||||
|
|
||||||
|
|
||||||
.. _builtincodecs:
|
.. _builtincodecs:
|
||||||
|
|
||||||
|
|
|
@ -360,6 +360,10 @@ Changes in the C API
|
||||||
:c:type:`unsigned long`.
|
:c:type:`unsigned long`.
|
||||||
(Contributed by Serhiy Storchaka in :issue:`6532`.)
|
(Contributed by Serhiy Storchaka in :issue:`6532`.)
|
||||||
|
|
||||||
|
- :c:func:`PyUnicode_AsWideCharString` now raises a :exc:`ValueError` if the
|
||||||
|
second argument is *NULL* and the :c:type:`wchar_t*` string contains null
|
||||||
|
characters. (Contributed by Serhiy Storchaka in :issue:`30708`.)
|
||||||
|
|
||||||
|
|
||||||
Removed
|
Removed
|
||||||
=======
|
=======
|
||||||
|
|
|
@ -134,7 +134,7 @@ class SlicesTestCase(unittest.TestCase):
|
||||||
dll.my_wcsdup.restype = POINTER(c_wchar)
|
dll.my_wcsdup.restype = POINTER(c_wchar)
|
||||||
dll.my_wcsdup.argtypes = POINTER(c_wchar),
|
dll.my_wcsdup.argtypes = POINTER(c_wchar),
|
||||||
dll.my_free.restype = None
|
dll.my_free.restype = None
|
||||||
res = dll.my_wcsdup(s)
|
res = dll.my_wcsdup(s[:-1])
|
||||||
self.assertEqual(res[:len(s)], s)
|
self.assertEqual(res[:len(s)], s)
|
||||||
self.assertEqual(res[:len(s):], s)
|
self.assertEqual(res[:len(s):], s)
|
||||||
self.assertEqual(res[len(s)-1:-1:-1], s[::-1])
|
self.assertEqual(res[len(s)-1:-1:-1], s[::-1])
|
||||||
|
@ -153,7 +153,7 @@ class SlicesTestCase(unittest.TestCase):
|
||||||
dll.my_wcsdup.restype = POINTER(c_long)
|
dll.my_wcsdup.restype = POINTER(c_long)
|
||||||
else:
|
else:
|
||||||
self.skipTest('Pointers to c_wchar are not supported')
|
self.skipTest('Pointers to c_wchar are not supported')
|
||||||
res = dll.my_wcsdup(s)
|
res = dll.my_wcsdup(s[:-1])
|
||||||
tmpl = list(range(ord("a"), ord("z")+1))
|
tmpl = list(range(ord("a"), ord("z")+1))
|
||||||
self.assertEqual(res[:len(s)-1], tmpl)
|
self.assertEqual(res[:len(s)-1], tmpl)
|
||||||
self.assertEqual(res[:len(s)-1:], tmpl)
|
self.assertEqual(res[:len(s)-1:], tmpl)
|
||||||
|
|
|
@ -1245,6 +1245,10 @@ Windows
|
||||||
C API
|
C API
|
||||||
-----
|
-----
|
||||||
|
|
||||||
|
- bpo-30708: PyUnicode_AsWideCharString() now raises a ValueError if the
|
||||||
|
second argument is NULL and the wchar_t\* string contains null
|
||||||
|
characters.
|
||||||
|
|
||||||
- bpo-16500: Deprecate PyOS_AfterFork() and add PyOS_BeforeFork(),
|
- bpo-16500: Deprecate PyOS_AfterFork() and add PyOS_BeforeFork(),
|
||||||
PyOS_AfterFork_Parent() and PyOS_AfterFork_Child().
|
PyOS_AfterFork_Parent() and PyOS_AfterFork_Child().
|
||||||
|
|
||||||
|
|
|
@ -304,18 +304,11 @@ _io__WindowsConsoleIO___init___impl(winconsoleio *self, PyObject *nameobj,
|
||||||
if (!d)
|
if (!d)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
Py_ssize_t length;
|
name = PyUnicode_AsWideCharString(decodedname, NULL);
|
||||||
name = PyUnicode_AsWideCharString(decodedname, &length);
|
|
||||||
console_type = _PyIO_get_console_type(decodedname);
|
console_type = _PyIO_get_console_type(decodedname);
|
||||||
Py_CLEAR(decodedname);
|
Py_CLEAR(decodedname);
|
||||||
if (name == NULL)
|
if (name == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (wcslen(name) != length) {
|
|
||||||
PyMem_Free(name);
|
|
||||||
PyErr_SetString(PyExc_ValueError, "embedded null character");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
s = mode;
|
s = mode;
|
||||||
|
|
|
@ -2953,8 +2953,7 @@ PyUnicode_FromFormat(const char *format, ...)
|
||||||
|
|
||||||
#ifdef HAVE_WCHAR_H
|
#ifdef HAVE_WCHAR_H
|
||||||
|
|
||||||
/* Helper function for PyUnicode_AsWideChar() and PyUnicode_AsWideCharString():
|
/* Convert a Unicode object to a wide character string.
|
||||||
convert a Unicode object to a wide character string.
|
|
||||||
|
|
||||||
- If w is NULL: return the number of wide characters (including the null
|
- If w is NULL: return the number of wide characters (including the null
|
||||||
character) required to convert the unicode object. Ignore size argument.
|
character) required to convert the unicode object. Ignore size argument.
|
||||||
|
@ -2962,14 +2961,18 @@ PyUnicode_FromFormat(const char *format, ...)
|
||||||
- Otherwise: return the number of wide characters (excluding the null
|
- Otherwise: return the number of wide characters (excluding the null
|
||||||
character) written into w. Write at most size wide characters (including
|
character) written into w. Write at most size wide characters (including
|
||||||
the null character). */
|
the null character). */
|
||||||
static Py_ssize_t
|
Py_ssize_t
|
||||||
unicode_aswidechar(PyObject *unicode,
|
PyUnicode_AsWideChar(PyObject *unicode,
|
||||||
wchar_t *w,
|
wchar_t *w,
|
||||||
Py_ssize_t size)
|
Py_ssize_t size)
|
||||||
{
|
{
|
||||||
Py_ssize_t res;
|
Py_ssize_t res;
|
||||||
const wchar_t *wstr;
|
const wchar_t *wstr;
|
||||||
|
|
||||||
|
if (unicode == NULL) {
|
||||||
|
PyErr_BadInternalCall();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
wstr = PyUnicode_AsUnicodeAndSize(unicode, &res);
|
wstr = PyUnicode_AsUnicodeAndSize(unicode, &res);
|
||||||
if (wstr == NULL)
|
if (wstr == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -2986,23 +2989,12 @@ unicode_aswidechar(PyObject *unicode,
|
||||||
return res + 1;
|
return res + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
Py_ssize_t
|
|
||||||
PyUnicode_AsWideChar(PyObject *unicode,
|
|
||||||
wchar_t *w,
|
|
||||||
Py_ssize_t size)
|
|
||||||
{
|
|
||||||
if (unicode == NULL) {
|
|
||||||
PyErr_BadInternalCall();
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return unicode_aswidechar(unicode, w, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
wchar_t*
|
wchar_t*
|
||||||
PyUnicode_AsWideCharString(PyObject *unicode,
|
PyUnicode_AsWideCharString(PyObject *unicode,
|
||||||
Py_ssize_t *size)
|
Py_ssize_t *size)
|
||||||
{
|
{
|
||||||
wchar_t* buffer;
|
const wchar_t *wstr;
|
||||||
|
wchar_t *buffer;
|
||||||
Py_ssize_t buflen;
|
Py_ssize_t buflen;
|
||||||
|
|
||||||
if (unicode == NULL) {
|
if (unicode == NULL) {
|
||||||
|
@ -3010,19 +3002,22 @@ PyUnicode_AsWideCharString(PyObject *unicode,
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
buflen = unicode_aswidechar(unicode, NULL, 0);
|
wstr = PyUnicode_AsUnicodeAndSize(unicode, &buflen);
|
||||||
if (buflen == -1)
|
if (wstr == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
buffer = PyMem_NEW(wchar_t, buflen);
|
}
|
||||||
|
if (size == NULL && wcslen(wstr) != (size_t)buflen) {
|
||||||
|
PyErr_SetString(PyExc_ValueError,
|
||||||
|
"embedded null character");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer = PyMem_NEW(wchar_t, buflen + 1);
|
||||||
if (buffer == NULL) {
|
if (buffer == NULL) {
|
||||||
PyErr_NoMemory();
|
PyErr_NoMemory();
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
buflen = unicode_aswidechar(unicode, buffer, buflen);
|
memcpy(buffer, wstr, (buflen + 1) * sizeof(wchar_t));
|
||||||
if (buflen == -1) {
|
|
||||||
PyMem_FREE(buffer);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
if (size != NULL)
|
if (size != NULL)
|
||||||
*size = buflen;
|
*size = buflen;
|
||||||
return buffer;
|
return buffer;
|
||||||
|
|
Loading…
Reference in New Issue