Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Fix a subprocess crash in Windows compatibility mode when
``STARTUPINFO.lpAttributeList`` is empty. Patch By Segev Finer.
3 changes: 2 additions & 1 deletion Modules/_winapi.c
Original file line number Diff line number Diff line change
Expand Up @@ -1140,7 +1140,8 @@ _winapi_CreateProcess_impl(PyObject *module,
NULL,
NULL,
inherit_handles,
creation_flags | EXTENDED_STARTUPINFO_PRESENT |
creation_flags |
(si.lpAttributeList ? EXTENDED_STARTUPINFO_PRESENT : 0) |

@eryksun eryksun Mar 1, 2018

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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;
    }
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 */

CREATE_UNICODE_ENVIRONMENT,
wenvironment,
current_directory,
Expand Down