bpo-32818: Fix a subprocess crash in Windows compatiblity mode#5948
bpo-32818: Fix a subprocess crash in Windows compatiblity mode#5948segevfiner wants to merge 2 commits into
Conversation
The crash happens when STARTUPINFO.lpAttributeList is empty.
| inherit_handles, | ||
| creation_flags | EXTENDED_STARTUPINFO_PRESENT | | ||
| creation_flags | | ||
| (si.lpAttributeList ? EXTENDED_STARTUPINFO_PRESENT : 0) | |
There was a problem hiding this comment.
It may be more resilient to also always allocate an attribute list, even if it's empty. That avoids any potential Windows bugs where a bad assumption is made based on the struct size and ignoring the creation flags. This could be done with the following changes in getattributelist:
value = PyObject_GetAttrString(obj, name);
if (!value) {
PyErr_Clear();
Py_INCREF(Py_None);
value = Py_None;
} else if (value != Py_None && !PyMapping_Check(value)) {
ret = -1;
PyErr_Format(PyExc_TypeError, "%s must be a mapping or None", name);
goto cleanup;
}
if (value != Py_None) {
attribute_list->handle_list = gethandlelist(value, "handle_list",
&handle_list_size);
if (attribute_list->handle_list == NULL && PyErr_Occurred()) {
ret = -1;
goto cleanup;
}
}
There was a problem hiding this comment.
Since this will always allocate the attribute list, it makes the change to the flags passed to CreateProcess redundant. I was contemplating a fix like this too. But I'm not sure which is the best or more robust fix for this.
There was a problem hiding this comment.
The simplest and most efficient solution is to omit the creation flag, as you implemented it. In Windows 10, the extended startup info creation flag gates further checks. If it's present in the creation flags, and the startup info is the right size, and the attribute list pointer isn't NULL, then CreateProcess calls BasepConvertWin32AttributeList to convert the attribute list to NT form. If the struct is the wrong size, it's handled as an invalid parameter.
That said, I'm more comfortable if the startup info is valid on its own. The docs don't explicitly say it's ok for lpAttributeList to be NULL, but I assumed it was. It's common for an optional parameter or field to be set to NULL when unused. If we omit the creation flag that indicates an extended startup info is present when we're actually using an extended startup info (as indicated by size, but then the flag is redundant), to me that seems like a nonsense hack. In that case I'd rather allocate an empty attribute list.
There was a problem hiding this comment.
I don't know how to fix.
I would suggest that add a comment like this, since this patch may be removed in several years later.
/* fix a bug of Windows Compatiblity Mode, bpo-32818 */…ocess-compatibility-crash
|
Closing as Windows 7 is not supported anymore and Python 3.9 is security fixes only. |
The crash happens when
STARTUPINFO.lpAttributeListis empty. (See https://bugs.python.org/msg313094).https://bugs.python.org/issue32818