bpo-36346: Do not use legacy Unicode C API in ctypes. (#21429) · python/cpython@d878349

@@ -1366,8 +1366,6 @@ WCharArray_get_value(CDataObject *self, void *Py_UNUSED(ignored))

13661366

static int

13671367

WCharArray_set_value(CDataObject *self, PyObject *value, void *Py_UNUSED(ignored))

13681368

{

1369-

Py_ssize_t result = 0;

1370-13711369

if (value == NULL) {

13721370

PyErr_SetString(PyExc_TypeError,

13731371

"can't delete attribute");

@@ -1378,29 +1376,24 @@ WCharArray_set_value(CDataObject *self, PyObject *value, void *Py_UNUSED(ignored

13781376

"unicode string expected instead of %s instance",

13791377

Py_TYPE(value)->tp_name);

13801378

return -1;

1381-

} else

1382-

Py_INCREF(value);

1379+

}

138313801381+

Py_ssize_t size = self->b_size / sizeof(wchar_t);

13841382

Py_ssize_t len = PyUnicode_AsWideChar(value, NULL, 0);

13851383

if (len < 0) {

13861384

return -1;

13871385

}

13881386

// PyUnicode_AsWideChar() returns number of wchars including trailing null byte,

13891387

// when it is called with NULL.

1390-

if (((size_t)len-1) > self->b_size/sizeof(wchar_t)) {

1388+

assert(len > 0);

1389+

if (len - 1 > size) {

13911390

PyErr_SetString(PyExc_ValueError, "string too long");

1392-

result = -1;

1393-

goto done;

1394-

}

1395-

result = PyUnicode_AsWideChar(value,

1396-

(wchar_t *)self->b_ptr,

1397-

self->b_size/sizeof(wchar_t));

1398-

if (result >= 0 && (size_t)result < self->b_size/sizeof(wchar_t))

1399-

((wchar_t *)self->b_ptr)[result] = (wchar_t)0;

1400-

done:

1401-

Py_DECREF(value);

1402-1403-

return result >= 0 ? 0 : -1;

1391+

return -1;

1392+

}

1393+

if (PyUnicode_AsWideChar(value, (wchar_t *)self->b_ptr, size) < 0) {

1394+

return -1;

1395+

}

1396+

return 0;

14041397

}

1405139814061399

static PyGetSetDef WCharArray_getsets[] = {

@@ -3484,10 +3477,12 @@ _validate_paramflags(PyTypeObject *type, PyObject *paramflags)

34843477

for (i = 0; i < len; ++i) {

34853478

PyObject *item = PyTuple_GET_ITEM(paramflags, i);

34863479

int flag;

3487-

char *name;

3480+

PyObject *name = Py_None;

34883481

PyObject *defval;

34893482

PyObject *typ;

3490-

if (!PyArg_ParseTuple(item, "i|ZO", &flag, &name, &defval)) {

3483+

if (!PyArg_ParseTuple(item, "i|OO", &flag, &name, &defval) ||

3484+

!(name == Py_None || PyUnicode_Check(name)))

3485+

{

34913486

PyErr_SetString(PyExc_TypeError,

34923487

"paramflags must be a sequence of (int [,string [,value]]) tuples");

34933488

return 0;