From 5513ad68713b13b6736f97b0db8ddc75bbbcbbb0 Mon Sep 17 00:00:00 2001 From: Inada Naoki Date: Fri, 15 Mar 2019 18:30:34 +0900 Subject: [PATCH 1/4] ctypes: remove use of legacy unicode API PyUnicode_AsUnicodeAndSize() -> PyUnicode_AsWideChar() --- Modules/_ctypes/_ctypes.c | 10 ++++------ Modules/_ctypes/cfield.c | 15 ++++++--------- 2 files changed, 10 insertions(+), 15 deletions(-) diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c index 0d95d2b6f76eceb..bee2764187fedde 100644 --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -1293,8 +1293,6 @@ static int WCharArray_set_value(CDataObject *self, PyObject *value, void *Py_UNUSED(ignored)) { Py_ssize_t result = 0; - Py_UNICODE *wstr; - Py_ssize_t len; if (value == NULL) { PyErr_SetString(PyExc_TypeError, @@ -1309,12 +1307,12 @@ WCharArray_set_value(CDataObject *self, PyObject *value, void *Py_UNUSED(ignored } else Py_INCREF(value); - wstr = PyUnicode_AsUnicodeAndSize(value, &len); - if (wstr == NULL) + Py_ssize_t len = PyUnicode_AsWideChar(value, NULL, 0); + if (len < 0) { return -1; + } if ((size_t)len > self->b_size/sizeof(wchar_t)) { - PyErr_SetString(PyExc_ValueError, - "string too long"); + PyErr_SetString(PyExc_ValueError, "string too long"); result = -1; goto done; } diff --git a/Modules/_ctypes/cfield.c b/Modules/_ctypes/cfield.c index 5f194e21550f7ba..693e500c267522e 100644 --- a/Modules/_ctypes/cfield.c +++ b/Modules/_ctypes/cfield.c @@ -1229,9 +1229,6 @@ U_get(void *ptr, Py_ssize_t size) static PyObject * U_set(void *ptr, PyObject *value, Py_ssize_t length) { - Py_UNICODE *wstr; - Py_ssize_t size; - /* It's easier to calculate in characters than in bytes */ length /= sizeof(wchar_t); @@ -1242,9 +1239,10 @@ U_set(void *ptr, PyObject *value, Py_ssize_t length) return NULL; } - wstr = PyUnicode_AsUnicodeAndSize(value, &size); - if (wstr == NULL) + Py_ssize_t size = PyUnicode_AsWideChar(value, NULL, 0); + if (size < 0) { return NULL; + } if (size > length) { PyErr_Format(PyExc_ValueError, "string too long (%zd, maximum length %zd)", @@ -1421,11 +1419,10 @@ BSTR_set(void *ptr, PyObject *value, Py_ssize_t size) /* create a BSTR from value */ if (value) { - wchar_t* wvalue; - Py_ssize_t wsize; - wvalue = PyUnicode_AsUnicodeAndSize(value, &wsize); - if (wvalue == NULL) + Py_ssize_t wsize = PyUnicode_AsWideChar(value, NULL, 0); + if (wsize < 0) { return NULL; + } if ((unsigned) wsize != wsize) { PyErr_SetString(PyExc_ValueError, "String too long for BSTR"); return NULL; From 4b8b223a03136507732cbcfe3fd340f07959fd4e Mon Sep 17 00:00:00 2001 From: Inada Naoki Date: Fri, 15 Mar 2019 18:37:13 +0900 Subject: [PATCH 2/4] fix --- Modules/_ctypes/cfield.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Modules/_ctypes/cfield.c b/Modules/_ctypes/cfield.c index 693e500c267522e..f47245804d757f6 100644 --- a/Modules/_ctypes/cfield.c +++ b/Modules/_ctypes/cfield.c @@ -1419,15 +1419,18 @@ BSTR_set(void *ptr, PyObject *value, Py_ssize_t size) /* create a BSTR from value */ if (value) { - Py_ssize_t wsize = PyUnicode_AsWideChar(value, NULL, 0); - if (wsize < 0) { + Py_ssize_t wsize; + wchar_t *wvalue = PyUnicode_AsWideCharString(value, &wsize); + if (wvalue == NULL) { return NULL; } if ((unsigned) wsize != wsize) { PyErr_SetString(PyExc_ValueError, "String too long for BSTR"); + PyMem_Free(wvalue); return NULL; } bstr = SysAllocStringLen(wvalue, (unsigned)wsize); + PyMem_Free(wvalue); } else bstr = NULL; From 22a78c142f4a4ca32aaeb38655a913b462a5354f Mon Sep 17 00:00:00 2001 From: Inada Naoki Date: Fri, 15 Mar 2019 18:55:03 +0900 Subject: [PATCH 3/4] fix --- Modules/_ctypes/_ctypes.c | 4 +++- Modules/_ctypes/cfield.c | 4 ++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c index bee2764187fedde..19ecc419cbb298b 100644 --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -1311,7 +1311,9 @@ WCharArray_set_value(CDataObject *self, PyObject *value, void *Py_UNUSED(ignored if (len < 0) { return -1; } - if ((size_t)len > self->b_size/sizeof(wchar_t)) { + // PyUnicode_AsWideChar() returns number of wchars including trailing NUL, + // when it is called with NULL. + if ((size_t)len-1 > self->b_size/sizeof(wchar_t)) { PyErr_SetString(PyExc_ValueError, "string too long"); result = -1; goto done; diff --git a/Modules/_ctypes/cfield.c b/Modules/_ctypes/cfield.c index f47245804d757f6..e94e1f857f879ae 100644 --- a/Modules/_ctypes/cfield.c +++ b/Modules/_ctypes/cfield.c @@ -1243,6 +1243,10 @@ U_set(void *ptr, PyObject *value, Py_ssize_t length) if (size < 0) { return NULL; } + // PyUnicode_AsWideChar() returns number of wchars including trailing NUL, + // when it is called with NULL. + size--; + assert(size >= 0); if (size > length) { PyErr_Format(PyExc_ValueError, "string too long (%zd, maximum length %zd)", From c5e610287eca7e20993ba957747752a7f1cdce3c Mon Sep 17 00:00:00 2001 From: Brett Cannon Date: Fri, 19 Apr 2019 15:31:10 +0900 Subject: [PATCH 4/4] Apply suggestions from code review Co-Authored-By: methane --- Modules/_ctypes/_ctypes.c | 4 ++-- Modules/_ctypes/cfield.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c index 19ecc419cbb298b..e231c9fa53ca85a 100644 --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -1311,9 +1311,9 @@ WCharArray_set_value(CDataObject *self, PyObject *value, void *Py_UNUSED(ignored if (len < 0) { return -1; } - // PyUnicode_AsWideChar() returns number of wchars including trailing NUL, + // PyUnicode_AsWideChar() returns number of wchars including trailing null byte, // when it is called with NULL. - if ((size_t)len-1 > self->b_size/sizeof(wchar_t)) { + if (((size_t)len-1) > self->b_size/sizeof(wchar_t)) { PyErr_SetString(PyExc_ValueError, "string too long"); result = -1; goto done; diff --git a/Modules/_ctypes/cfield.c b/Modules/_ctypes/cfield.c index e94e1f857f879ae..157c32fd90967f5 100644 --- a/Modules/_ctypes/cfield.c +++ b/Modules/_ctypes/cfield.c @@ -1243,7 +1243,7 @@ U_set(void *ptr, PyObject *value, Py_ssize_t length) if (size < 0) { return NULL; } - // PyUnicode_AsWideChar() returns number of wchars including trailing NUL, + // PyUnicode_AsWideChar() returns number of wchars including trailing null byte, // when it is called with NULL. size--; assert(size >= 0);