bpo-36346: Do not use legacy Unicode C API in ctypes. (#21429)

This commit is contained in:
Serhiy Storchaka 2020-07-10 11:17:21 +03:00 committed by GitHub
parent 0f9aa47bab
commit d878349bac
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 20 additions and 28 deletions

View File

@ -1366,8 +1366,6 @@ WCharArray_get_value(CDataObject *self, void *Py_UNUSED(ignored))
static int static int
WCharArray_set_value(CDataObject *self, PyObject *value, void *Py_UNUSED(ignored)) WCharArray_set_value(CDataObject *self, PyObject *value, void *Py_UNUSED(ignored))
{ {
Py_ssize_t result = 0;
if (value == NULL) { if (value == NULL) {
PyErr_SetString(PyExc_TypeError, PyErr_SetString(PyExc_TypeError,
"can't delete attribute"); "can't delete attribute");
@ -1378,29 +1376,24 @@ WCharArray_set_value(CDataObject *self, PyObject *value, void *Py_UNUSED(ignored
"unicode string expected instead of %s instance", "unicode string expected instead of %s instance",
Py_TYPE(value)->tp_name); Py_TYPE(value)->tp_name);
return -1; return -1;
} else }
Py_INCREF(value);
Py_ssize_t size = self->b_size / sizeof(wchar_t);
Py_ssize_t len = PyUnicode_AsWideChar(value, NULL, 0); Py_ssize_t len = PyUnicode_AsWideChar(value, NULL, 0);
if (len < 0) { if (len < 0) {
return -1; return -1;
} }
// PyUnicode_AsWideChar() returns number of wchars including trailing null byte, // PyUnicode_AsWideChar() returns number of wchars including trailing null byte,
// when it is called with NULL. // when it is called with NULL.
if (((size_t)len-1) > self->b_size/sizeof(wchar_t)) { assert(len > 0);
if (len - 1 > size) {
PyErr_SetString(PyExc_ValueError, "string too long"); PyErr_SetString(PyExc_ValueError, "string too long");
result = -1; return -1;
goto done;
} }
result = PyUnicode_AsWideChar(value, if (PyUnicode_AsWideChar(value, (wchar_t *)self->b_ptr, size) < 0) {
(wchar_t *)self->b_ptr, return -1;
self->b_size/sizeof(wchar_t)); }
if (result >= 0 && (size_t)result < self->b_size/sizeof(wchar_t)) return 0;
((wchar_t *)self->b_ptr)[result] = (wchar_t)0;
done:
Py_DECREF(value);
return result >= 0 ? 0 : -1;
} }
static PyGetSetDef WCharArray_getsets[] = { static PyGetSetDef WCharArray_getsets[] = {
@ -3484,10 +3477,12 @@ _validate_paramflags(PyTypeObject *type, PyObject *paramflags)
for (i = 0; i < len; ++i) { for (i = 0; i < len; ++i) {
PyObject *item = PyTuple_GET_ITEM(paramflags, i); PyObject *item = PyTuple_GET_ITEM(paramflags, i);
int flag; int flag;
char *name; PyObject *name = Py_None;
PyObject *defval; PyObject *defval;
PyObject *typ; PyObject *typ;
if (!PyArg_ParseTuple(item, "i|ZO", &flag, &name, &defval)) { if (!PyArg_ParseTuple(item, "i|OO", &flag, &name, &defval) ||
!(name == Py_None || PyUnicode_Check(name)))
{
PyErr_SetString(PyExc_TypeError, PyErr_SetString(PyExc_TypeError,
"paramflags must be a sequence of (int [,string [,value]]) tuples"); "paramflags must be a sequence of (int [,string [,value]]) tuples");
return 0; return 0;

View File

@ -1300,7 +1300,6 @@ module. load_flags are as defined for LoadLibraryEx in the\n\
Windows API.\n"; Windows API.\n";
static PyObject *load_library(PyObject *self, PyObject *args) static PyObject *load_library(PyObject *self, PyObject *args)
{ {
const WCHAR *name;
PyObject *nameobj; PyObject *nameobj;
int load_flags = 0; int load_flags = 0;
HMODULE hMod; HMODULE hMod;
@ -1309,14 +1308,14 @@ static PyObject *load_library(PyObject *self, PyObject *args)
if (!PyArg_ParseTuple(args, "U|i:LoadLibrary", &nameobj, &load_flags)) if (!PyArg_ParseTuple(args, "U|i:LoadLibrary", &nameobj, &load_flags))
return NULL; return NULL;
name = _PyUnicode_AsUnicode(nameobj);
if (!name)
return NULL;
if (PySys_Audit("ctypes.dlopen", "O", nameobj) < 0) { if (PySys_Audit("ctypes.dlopen", "O", nameobj) < 0) {
return NULL; return NULL;
} }
WCHAR *name = PyUnicode_AsWideCharString(nameobj, NULL);
if (!name)
return NULL;
Py_BEGIN_ALLOW_THREADS Py_BEGIN_ALLOW_THREADS
/* bpo-36085: Limit DLL search directories to avoid pre-loading /* bpo-36085: Limit DLL search directories to avoid pre-loading
* attacks and enable use of the AddDllDirectory function. * attacks and enable use of the AddDllDirectory function.
@ -1325,6 +1324,7 @@ static PyObject *load_library(PyObject *self, PyObject *args)
err = hMod ? 0 : GetLastError(); err = hMod ? 0 : GetLastError();
Py_END_ALLOW_THREADS Py_END_ALLOW_THREADS
PyMem_Free(name);
if (err == ERROR_MOD_NOT_FOUND) { if (err == ERROR_MOD_NOT_FOUND) {
PyErr_Format(PyExc_FileNotFoundError, PyErr_Format(PyExc_FileNotFoundError,
("Could not find module '%.500S' (or one of its " ("Could not find module '%.500S' (or one of its "

View File

@ -1220,11 +1220,8 @@ U_set(void *ptr, PyObject *value, Py_ssize_t length)
"string too long (%zd, maximum length %zd)", "string too long (%zd, maximum length %zd)",
size, length); size, length);
return NULL; return NULL;
} else if (size < length-1) }
/* copy terminating NUL character if there is space */ if (PyUnicode_AsWideChar(value, (wchar_t *)ptr, length) == -1) {
size += 1;
if (PyUnicode_AsWideChar(value, (wchar_t *)ptr, size) == -1) {
return NULL; return NULL;
} }