diff options
author | Serhiy Storchaka <storchaka@gmail.com> | 2019-03-28 14:01:34 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-03-28 14:01:34 (GMT) |
commit | 8abd7c7e37714ce0c42f871f81e52f14c155d1bd (patch) | |
tree | 3247897c4dff561cd214150e9061c0dcf79dc5b0 /Modules | |
parent | cda139d1ded6708665b53e4ed32ccc1d2627e1da (diff) | |
download | cpython-8abd7c7e37714ce0c42f871f81e52f14c155d1bd.zip cpython-8abd7c7e37714ce0c42f871f81e52f14c155d1bd.tar.gz cpython-8abd7c7e37714ce0c42f871f81e52f14c155d1bd.tar.bz2 |
bpo-36387: Refactor getenvironment() in _winapi.c. (GH-12482)
Make it doing less memory allocations and using the modern C API.
Diffstat (limited to 'Modules')
-rw-r--r-- | Modules/_winapi.c | 80 |
1 files changed, 34 insertions, 46 deletions
diff --git a/Modules/_winapi.c b/Modules/_winapi.c index e7b221d..2eb708e 100644 --- a/Modules/_winapi.c +++ b/Modules/_winapi.c @@ -752,12 +752,12 @@ gethandle(PyObject* obj, const char* name) return ret; } -static PyObject* +static wchar_t * getenvironment(PyObject* environment) { Py_ssize_t i, envsize, totalsize; - Py_UCS4 *buffer = NULL, *p, *end; - PyObject *keys, *values, *res; + wchar_t *buffer = NULL, *p, *end; + PyObject *keys, *values; /* convert environment dictionary to windows environment string */ if (! PyMapping_Check(environment)) { @@ -775,8 +775,8 @@ getenvironment(PyObject* environment) goto error; } - envsize = PySequence_Fast_GET_SIZE(keys); - if (PySequence_Fast_GET_SIZE(values) != envsize) { + envsize = PyList_GET_SIZE(keys); + if (PyList_GET_SIZE(values) != envsize) { PyErr_SetString(PyExc_RuntimeError, "environment changed size during iteration"); goto error; @@ -784,8 +784,9 @@ getenvironment(PyObject* environment) totalsize = 1; /* trailing null character */ for (i = 0; i < envsize; i++) { - PyObject* key = PySequence_Fast_GET_ITEM(keys, i); - PyObject* value = PySequence_Fast_GET_ITEM(values, i); + PyObject* key = PyList_GET_ITEM(keys, i); + PyObject* value = PyList_GET_ITEM(values, i); + Py_ssize_t size; if (! PyUnicode_Check(key) || ! PyUnicode_Check(value)) { PyErr_SetString(PyExc_TypeError, @@ -806,19 +807,25 @@ getenvironment(PyObject* environment) PyErr_SetString(PyExc_ValueError, "illegal environment variable name"); goto error; } - if (totalsize > PY_SSIZE_T_MAX - PyUnicode_GET_LENGTH(key) - 1) { + + size = PyUnicode_AsWideChar(key, NULL, 0); + assert(size > 1); + if (totalsize > PY_SSIZE_T_MAX - size) { PyErr_SetString(PyExc_OverflowError, "environment too long"); goto error; } - totalsize += PyUnicode_GET_LENGTH(key) + 1; /* +1 for '=' */ - if (totalsize > PY_SSIZE_T_MAX - PyUnicode_GET_LENGTH(value) - 1) { + totalsize += size; /* including '=' */ + + size = PyUnicode_AsWideChar(value, NULL, 0); + assert(size > 0); + if (totalsize > PY_SSIZE_T_MAX - size) { PyErr_SetString(PyExc_OverflowError, "environment too long"); goto error; } - totalsize += PyUnicode_GET_LENGTH(value) + 1; /* +1 for '\0' */ + totalsize += size; /* including trailing '\0' */ } - buffer = PyMem_NEW(Py_UCS4, totalsize); + buffer = PyMem_NEW(wchar_t, totalsize); if (! buffer) { PyErr_NoMemory(); goto error; @@ -827,34 +834,25 @@ getenvironment(PyObject* environment) end = buffer + totalsize; for (i = 0; i < envsize; i++) { - PyObject* key = PySequence_Fast_GET_ITEM(keys, i); - PyObject* value = PySequence_Fast_GET_ITEM(values, i); - if (!PyUnicode_AsUCS4(key, p, end - p, 0)) - goto error; - p += PyUnicode_GET_LENGTH(key); - *p++ = '='; - if (!PyUnicode_AsUCS4(value, p, end - p, 0)) - goto error; - p += PyUnicode_GET_LENGTH(value); - *p++ = '\0'; + PyObject* key = PyList_GET_ITEM(keys, i); + PyObject* value = PyList_GET_ITEM(values, i); + Py_ssize_t size = PyUnicode_AsWideChar(key, p, end - p); + assert(1 <= size && size < end - p); + p += size; + *p++ = L'='; + size = PyUnicode_AsWideChar(value, p, end - p); + assert(0 <= size && size < end - p); + p += size + 1; } - /* add trailing null byte */ - *p++ = '\0'; + /* add trailing null character */ + *p++ = L'\0'; assert(p == end); - Py_XDECREF(keys); - Py_XDECREF(values); - - res = PyUnicode_FromKindAndData(PyUnicode_4BYTE_KIND, buffer, p - buffer); - PyMem_Free(buffer); - return res; - error: - PyMem_Free(buffer); Py_XDECREF(keys); Py_XDECREF(values); - return NULL; + return buffer; } static LPHANDLE @@ -1053,8 +1051,7 @@ _winapi_CreateProcess_impl(PyObject *module, BOOL result; PROCESS_INFORMATION pi; STARTUPINFOEXW si; - PyObject *environment = NULL; - wchar_t *wenvironment; + wchar_t *wenvironment = NULL; wchar_t *command_line_copy = NULL; AttributeList attribute_list = {0}; @@ -1071,20 +1068,11 @@ _winapi_CreateProcess_impl(PyObject *module, goto cleanup; if (env_mapping != Py_None) { - environment = getenvironment(env_mapping); - if (environment == NULL) { - goto cleanup; - } - /* contains embedded null characters */ - wenvironment = PyUnicode_AsUnicode(environment); + wenvironment = getenvironment(env_mapping); if (wenvironment == NULL) { goto cleanup; } } - else { - environment = NULL; - wenvironment = NULL; - } if (getattributelist(startup_info, "lpAttributeList", &attribute_list) < 0) goto cleanup; @@ -1131,7 +1119,7 @@ _winapi_CreateProcess_impl(PyObject *module, cleanup: PyMem_Free(command_line_copy); - Py_XDECREF(environment); + PyMem_Free(wenvironment); freeattributelist(&attribute_list); return ret; |