Skip to content

Commit 9d062d6

Browse files
authored
ctypes: remove use of legacy unicode API (GH-12340)
PyUnicode_AsUnicodeAndSize() -> PyUnicode_AsWideChar()
1 parent e8113f5 commit 9d062d6

File tree

2 files changed

+19
-15
lines changed

2 files changed

+19
-15
lines changed

Modules/_ctypes/_ctypes.c

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1304,8 +1304,6 @@ static int
13041304
WCharArray_set_value(CDataObject *self, PyObject *value, void *Py_UNUSED(ignored))
13051305
{
13061306
Py_ssize_t result = 0;
1307-
Py_UNICODE *wstr;
1308-
Py_ssize_t len;
13091307

13101308
if (value == NULL) {
13111309
PyErr_SetString(PyExc_TypeError,
@@ -1320,12 +1318,14 @@ WCharArray_set_value(CDataObject *self, PyObject *value, void *Py_UNUSED(ignored
13201318
} else
13211319
Py_INCREF(value);
13221320

1323-
wstr = PyUnicode_AsUnicodeAndSize(value, &len);
1324-
if (wstr == NULL)
1321+
Py_ssize_t len = PyUnicode_AsWideChar(value, NULL, 0);
1322+
if (len < 0) {
13251323
return -1;
1326-
if ((size_t)len > self->b_size/sizeof(wchar_t)) {
1327-
PyErr_SetString(PyExc_ValueError,
1328-
"string too long");
1324+
}
1325+
// PyUnicode_AsWideChar() returns number of wchars including trailing null byte,
1326+
// when it is called with NULL.
1327+
if (((size_t)len-1) > self->b_size/sizeof(wchar_t)) {
1328+
PyErr_SetString(PyExc_ValueError, "string too long");
13291329
result = -1;
13301330
goto done;
13311331
}

Modules/_ctypes/cfield.c

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1229,9 +1229,6 @@ U_get(void *ptr, Py_ssize_t size)
12291229
static PyObject *
12301230
U_set(void *ptr, PyObject *value, Py_ssize_t length)
12311231
{
1232-
Py_UNICODE *wstr;
1233-
Py_ssize_t size;
1234-
12351232
/* It's easier to calculate in characters than in bytes */
12361233
length /= sizeof(wchar_t);
12371234

@@ -1242,9 +1239,14 @@ U_set(void *ptr, PyObject *value, Py_ssize_t length)
12421239
return NULL;
12431240
}
12441241

1245-
wstr = PyUnicode_AsUnicodeAndSize(value, &size);
1246-
if (wstr == NULL)
1242+
Py_ssize_t size = PyUnicode_AsWideChar(value, NULL, 0);
1243+
if (size < 0) {
12471244
return NULL;
1245+
}
1246+
// PyUnicode_AsWideChar() returns number of wchars including trailing null byte,
1247+
// when it is called with NULL.
1248+
size--;
1249+
assert(size >= 0);
12481250
if (size > length) {
12491251
PyErr_Format(PyExc_ValueError,
12501252
"string too long (%zd, maximum length %zd)",
@@ -1421,16 +1423,18 @@ BSTR_set(void *ptr, PyObject *value, Py_ssize_t size)
14211423

14221424
/* create a BSTR from value */
14231425
if (value) {
1424-
wchar_t* wvalue;
14251426
Py_ssize_t wsize;
1426-
wvalue = PyUnicode_AsUnicodeAndSize(value, &wsize);
1427-
if (wvalue == NULL)
1427+
wchar_t *wvalue = PyUnicode_AsWideCharString(value, &wsize);
1428+
if (wvalue == NULL) {
14281429
return NULL;
1430+
}
14291431
if ((unsigned) wsize != wsize) {
14301432
PyErr_SetString(PyExc_ValueError, "String too long for BSTR");
1433+
PyMem_Free(wvalue);
14311434
return NULL;
14321435
}
14331436
bstr = SysAllocStringLen(wvalue, (unsigned)wsize);
1437+
PyMem_Free(wvalue);
14341438
} else
14351439
bstr = NULL;
14361440

0 commit comments

Comments
 (0)