Skip to content

Commit 0edffa3

Browse files
[3.6] bpo-30708: Check for null characters in PyUnicode_AsWideCharString(). (GH-2285) (#2443)
Raise a ValueError if the second argument is NULL and the wchar_t\* string contains null characters.. (cherry picked from commit e613e6a)
1 parent 35d2ca2 commit 0edffa3

File tree

12 files changed

+50
-20
lines changed

12 files changed

+50
-20
lines changed

Include/unicodeobject.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1063,6 +1063,12 @@ PyAPI_FUNC(wchar_t*) PyUnicode_AsWideCharString(
10631063
);
10641064

10651065
#ifndef Py_LIMITED_API
1066+
/* Similar to PyUnicode_AsWideCharString(unicode, NULL), but check if
1067+
the string contains null characters. */
1068+
PyAPI_FUNC(wchar_t*) _PyUnicode_AsWideCharString(
1069+
PyObject *unicode /* Unicode object */
1070+
);
1071+
10661072
PyAPI_FUNC(void*) _PyUnicode_AsKind(PyObject *s, unsigned int kind);
10671073
#endif
10681074

Lib/ctypes/test/test_slicing.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ def test_wchar_ptr(self):
134134
dll.my_wcsdup.restype = POINTER(c_wchar)
135135
dll.my_wcsdup.argtypes = POINTER(c_wchar),
136136
dll.my_free.restype = None
137-
res = dll.my_wcsdup(s)
137+
res = dll.my_wcsdup(s[:-1])
138138
self.assertEqual(res[:len(s)], s)
139139
self.assertEqual(res[:len(s):], s)
140140
self.assertEqual(res[len(s)-1:-1:-1], s[::-1])
@@ -153,7 +153,7 @@ def test_wchar_ptr(self):
153153
dll.my_wcsdup.restype = POINTER(c_long)
154154
else:
155155
self.skipTest('Pointers to c_wchar are not supported')
156-
res = dll.my_wcsdup(s)
156+
res = dll.my_wcsdup(s[:-1])
157157
tmpl = list(range(ord("a"), ord("z")+1))
158158
self.assertEqual(res[:len(s)-1], tmpl)
159159
self.assertEqual(res[:len(s)-1:], tmpl)

Modules/_ctypes/callproc.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -668,7 +668,7 @@ static int ConvParam(PyObject *obj, Py_ssize_t index, struct argument *pa)
668668
#ifdef CTYPES_UNICODE
669669
if (PyUnicode_Check(obj)) {
670670
pa->ffi_type = &ffi_type_pointer;
671-
pa->value.p = PyUnicode_AsWideCharString(obj, NULL);
671+
pa->value.p = _PyUnicode_AsWideCharString(obj);
672672
if (pa->value.p == NULL)
673673
return -1;
674674
pa->keep = PyCapsule_New(pa->value.p, CTYPES_CAPSULE_NAME_PYMEM, pymem_destructor);

Modules/_ctypes/cfield.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1372,7 +1372,7 @@ Z_set(void *ptr, PyObject *value, Py_ssize_t size)
13721372

13731373
/* We must create a wchar_t* buffer from the unicode object,
13741374
and keep it alive */
1375-
buffer = PyUnicode_AsWideCharString(value, NULL);
1375+
buffer = _PyUnicode_AsWideCharString(value);
13761376
if (!buffer)
13771377
return NULL;
13781378
keep = PyCapsule_New(buffer, CTYPES_CFIELD_CAPSULE_NAME_PYMEM, pymem_destructor);

Modules/_cursesmodule.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -345,7 +345,7 @@ PyCurses_ConvertToString(PyCursesWindowObject *win, PyObject *obj,
345345
if (PyUnicode_Check(obj)) {
346346
#ifdef HAVE_NCURSESW
347347
assert (wstr != NULL);
348-
*wstr = PyUnicode_AsWideCharString(obj, NULL);
348+
*wstr = _PyUnicode_AsWideCharString(obj);
349349
if (*wstr == NULL)
350350
return 0;
351351
return 2;

Modules/_io/winconsoleio.c

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ char _PyIO_get_console_type(PyObject *path_or_fd) {
7979
PyErr_Clear();
8080
return '\0';
8181
}
82-
decoded_wstr = PyUnicode_AsWideCharString(decoded, NULL);
82+
decoded_wstr = _PyUnicode_AsWideCharString(decoded);
8383
Py_CLEAR(decoded);
8484
if (!decoded_wstr) {
8585
PyErr_Clear();
@@ -311,8 +311,7 @@ _io__WindowsConsoleIO___init___impl(winconsoleio *self, PyObject *nameobj,
311311
if (!d)
312312
return -1;
313313

314-
Py_ssize_t length;
315-
name = PyUnicode_AsWideCharString(decodedname, &length);
314+
name = _PyUnicode_AsWideCharString(decodedname);
316315
console_type = _PyIO_get_console_type(decodedname);
317316
Py_CLEAR(decodedname);
318317
if (name == NULL)
@@ -322,12 +321,6 @@ _io__WindowsConsoleIO___init___impl(winconsoleio *self, PyObject *nameobj,
322321
"Cannot open non-console file");
323322
return -1;
324323
}
325-
326-
if (wcslen(name) != length) {
327-
PyMem_Free(name);
328-
PyErr_SetString(PyExc_ValueError, "embedded null character");
329-
return -1;
330-
}
331324
}
332325

333326
s = mode;

Modules/_localemodule.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -215,10 +215,10 @@ PyLocale_strcoll(PyObject* self, PyObject* args)
215215
if (!PyArg_ParseTuple(args, "UU:strcoll", &os1, &os2))
216216
return NULL;
217217
/* Convert the unicode strings to wchar[]. */
218-
ws1 = PyUnicode_AsWideCharString(os1, NULL);
218+
ws1 = _PyUnicode_AsWideCharString(os1);
219219
if (ws1 == NULL)
220220
goto done;
221-
ws2 = PyUnicode_AsWideCharString(os2, NULL);
221+
ws2 = _PyUnicode_AsWideCharString(os2);
222222
if (ws2 == NULL)
223223
goto done;
224224
/* Collate the strings. */

Modules/_tkinter.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3615,7 +3615,7 @@ PyInit__tkinter(void)
36153615
return NULL;
36163616
}
36173617
if (str_path != NULL) {
3618-
wcs_path = PyUnicode_AsWideCharString(str_path, NULL);
3618+
wcs_path = _PyUnicode_AsWideCharString(str_path);
36193619
if (wcs_path == NULL) {
36203620
return NULL;
36213621
}

Modules/overlapped.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1151,7 +1151,7 @@ ConnectPipe(OverlappedObject *self, PyObject *args)
11511151
if (!PyArg_ParseTuple(args, "U", &AddressObj))
11521152
return NULL;
11531153

1154-
Address = PyUnicode_AsWideCharString(AddressObj, NULL);
1154+
Address = _PyUnicode_AsWideCharString(AddressObj);
11551155
if (Address == NULL)
11561156
return NULL;
11571157

Modules/timemodule.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -607,7 +607,7 @@ time_strftime(PyObject *self, PyObject *args)
607607
buf.tm_isdst = 1;
608608

609609
#ifdef HAVE_WCSFTIME
610-
format = PyUnicode_AsWideCharString(format_arg, NULL);
610+
format = _PyUnicode_AsWideCharString(format_arg);
611611
if (format == NULL)
612612
return NULL;
613613
fmt = format;

Objects/unicodeobject.c

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3017,6 +3017,37 @@ PyUnicode_AsWideCharString(PyObject *unicode,
30173017
return buffer;
30183018
}
30193019

3020+
wchar_t*
3021+
_PyUnicode_AsWideCharString(PyObject *unicode)
3022+
{
3023+
const wchar_t *wstr;
3024+
wchar_t *buffer;
3025+
Py_ssize_t buflen;
3026+
3027+
if (unicode == NULL) {
3028+
PyErr_BadInternalCall();
3029+
return NULL;
3030+
}
3031+
3032+
wstr = PyUnicode_AsUnicodeAndSize(unicode, &buflen);
3033+
if (wstr == NULL) {
3034+
return NULL;
3035+
}
3036+
if (wcslen(wstr) != (size_t)buflen) {
3037+
PyErr_SetString(PyExc_ValueError,
3038+
"embedded null character");
3039+
return NULL;
3040+
}
3041+
3042+
buffer = PyMem_NEW(wchar_t, buflen + 1);
3043+
if (buffer == NULL) {
3044+
PyErr_NoMemory();
3045+
return NULL;
3046+
}
3047+
memcpy(buffer, wstr, (buflen + 1) * sizeof(wchar_t));
3048+
return buffer;
3049+
}
3050+
30203051
#endif /* HAVE_WCHAR_H */
30213052

30223053
PyObject *

PC/winsound.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ winsound_PlaySound_impl(PyObject *module, PyObject *sound, int flags)
101101
Py_TYPE(sound)->tp_name);
102102
return NULL;
103103
}
104-
wsound = PyUnicode_AsWideCharString(sound, NULL);
104+
wsound = _PyUnicode_AsWideCharString(sound);
105105
if (wsound == NULL) {
106106
return NULL;
107107
}

0 commit comments

Comments
 (0)