bpo-32745: Fix a regression in the handling of ctypes' c_wchar_p type (#8721)

Embedded nulls would cause a ValueError to be raised. Thanks go to
Eryk Sun for their analysis.

Co-authored-by: Łukasz Langa <lukasz@langa.pl>
This commit is contained in:
Zackery Spytz 2021-05-02 03:40:01 -07:00 committed by GitHub
parent 518f8b5dd5
commit 73766b0341
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 13 additions and 1 deletions

View File

@ -26,6 +26,14 @@ class UnicodeTestCase(unittest.TestCase):
self.assertEqual(buf[::2], 'a\xe4\xfc') self.assertEqual(buf[::2], 'a\xe4\xfc')
self.assertEqual(buf[6:5:-1], "") self.assertEqual(buf[6:5:-1], "")
def test_embedded_null(self):
class TestStruct(ctypes.Structure):
_fields_ = [("unicode", ctypes.c_wchar_p)]
t = TestStruct()
# This would raise a ValueError:
t.unicode = "foo\0bar\0\0"
func = ctypes.CDLL(_ctypes_test.__file__)._testfunc_p_p func = ctypes.CDLL(_ctypes_test.__file__)._testfunc_p_p
class StringTestCase(UnicodeTestCase): class StringTestCase(UnicodeTestCase):

View File

@ -0,0 +1,3 @@
Fix a regression in the handling of ctypes' :data:`ctypes.c_wchar_p` type:
embedded null characters would cause a :exc:`ValueError` to be raised. Patch
by Zackery Spytz.

View File

@ -1341,6 +1341,7 @@ Z_set(void *ptr, PyObject *value, Py_ssize_t size)
{ {
PyObject *keep; PyObject *keep;
wchar_t *buffer; wchar_t *buffer;
Py_ssize_t bsize;
if (value == Py_None) { if (value == Py_None) {
*(wchar_t **)ptr = NULL; *(wchar_t **)ptr = NULL;
@ -1364,7 +1365,7 @@ Z_set(void *ptr, PyObject *value, Py_ssize_t size)
/* We must create a wchar_t* buffer from the unicode object, /* We must create a wchar_t* buffer from the unicode object,
and keep it alive */ and keep it alive */
buffer = PyUnicode_AsWideCharString(value, NULL); buffer = PyUnicode_AsWideCharString(value, &bsize);
if (!buffer) if (!buffer)
return NULL; return NULL;
keep = PyCapsule_New(buffer, CTYPES_CFIELD_CAPSULE_NAME_PYMEM, pymem_destructor); keep = PyCapsule_New(buffer, CTYPES_CFIELD_CAPSULE_NAME_PYMEM, pymem_destructor);