winapi_createprocess takes env_mapping dictionary as a parameter, mapping variables to their env. values. Dictionary with pathologically large values will cause an integer overflow during computation of total space required to store all key-value pairs
File: Modules\_winapi.c
static PyObject*
getenvironment(PyObject* environment)
{
Py_ssize_t i, envsize, totalsize;
...
envsize = PyMapping_Length(environment);
keys = PyMapping_Keys(environment);
values = PyMapping_Values(environment);
if (!keys || !values)
goto error;
totalsize = 1; /* trailing null character */
for (i = 0; i < envsize; i++) {
PyObject* key = PyList_GET_ITEM(keys, i);
PyObject* value = PyList_GET_ITEM(values, i);
if (! PyUnicode_Check(key) || ! PyUnicode_Check(value)) {
PyErr_SetString(PyExc_TypeError,
"environment can only contain strings");
goto error;
}
totalsize += PyUnicode_GET_LENGTH(key) + 1; /* +1 for '=' */
1 totalsize += PyUnicode_GET_LENGTH(value) + 1; /* +1 for '\0' */
}
2 buffer = PyMem_Malloc(totalsize * sizeof(Py_UCS4));
if (! buffer)
goto error;
p = buffer;
3 end = buffer + totalsize;
4 for (i = 0; i < envsize; i++) {
PyObject* key = PyList_GET_ITEM(keys, i);
PyObject* value = PyList_GET_ITEM(values, i);
X if (!PyUnicode_AsUCS4(key, p, end - p, 0))
goto error;
p += PyUnicode_GET_LENGTH(key);
X *p++ = '=';
X if (!PyUnicode_AsUCS4(value, p, end - p, 0))
goto error;
p += PyUnicode_GET_LENGTH(value);
X *p++ = '\0';
}
1. no overflow checks. We can set totalsize to 2^30, with a crafted dictionary.
2. totalsize*4 == 0, so buffer is 0-bytes long
3. end = buffer+2^30
4. envsize == len(env_mapping). We can make this variable as large as we like.
X. write past the buffer's end. Note size checks in PyUnicode_AsUCS4 are inefficient, because the size variable (end-p) is very large.
|