classification
Title: _Py_CheckPython3 uses uninitialized dllpath when embedder sets module path with Py_SetPath
Type: behavior Stage: resolved
Components: Windows Versions: Python 3.8
process
Status: closed Resolution: fixed
Dependencies: Superseder:
Assigned To: Nosy List: Tibor Csonka, paul.moore, steve.dower, tim.golden, vstinner, zach.ware
Priority: normal Keywords:

Created on 2017-03-10 04:58 by Tibor Csonka, last changed 2019-05-27 15:11 by vstinner. This issue is now closed.

Messages (4)
msg289334 - (view) Author: Tibor Csonka (Tibor Csonka) Date: 2017-03-10 04:58
When Py_SetPath is used to set up module path at initialization, the Py_SetPath causes getpathp.c::calculate_path not to be called. However, calculate path is the only function calling getpathp.c::get_progpath which initializes the local dllpath static variable.

Later the interpreter tries to load python3.dll and uses dllpath which is empty by default. This empty path gets joined with \python3.dll and \DLLs\python3.dll which is used in the LoadLibraryExW resulting in loading python3.dll from the root location of the windows drive the application is running from.

The behavior was reproduced using PyInstaller but it is present in any embedding application which uses Py_SetPath.
msg289364 - (view) Author: Steve Dower (steve.dower) * (Python committer) Date: 2017-03-10 14:23
I thought we'd documented that if you set the path when embedding you should also set the program name, but perhaps not (didn't check just now). If not, we should do that.

We shouldn't be loading python3.dll anywhere. Are you sure that's in CPython? Do you have a reference to the source file?
msg289412 - (view) Author: Steve Dower (steve.dower) * (Python committer) Date: 2017-03-10 21:50
Ah, I see. We force load it in PC/getpathp.c to ensure that it's ours and not another version's python3.dll.

We should probably refactor the GetModuleFileNameW call into its own function so we can call it from anywhere we need.
msg343638 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2019-05-27 15:11
> When Py_SetPath is used to set up module path at initialization, the Py_SetPath causes getpathp.c::calculate_path not to be called. However, calculate path is the only function calling getpathp.c::get_progpath which initializes the local dllpath static variable.

I fixed this issue in Python 3.8 with this commit:

commit 410759fba80aded5247b693c60745aa16906f3bb
Author: Victor Stinner <vstinner@redhat.com>
Date:   Sat May 18 04:17:01 2019 +0200

    bpo-36763: Remove _PyCoreConfig.dll_path (GH-13402)

I modified Py_SetPath() like that:

-    new_config.dll_path = _PyMem_RawWcsdup(L"");
+    new_config.dll_path = _Py_GetDLLPath();

Py_SetPath() no longer sets dll_path to an empty string.

Since we only got one bug report and I believe that Tibor Csonka found a way to workaround the issue since he reported it, I close the issue.

Please reopen/comment the issue if you would like to get this issue fixed in Python 3.7 as well.

--

Moreover, the PEP 587 now has a better API to configure embedded Python. I just implemented this PEP in bpo-36763.
History
Date User Action Args
2019-05-27 15:11:15vstinnersetstatus: open -> closed
stage: needs patch -> resolved
resolution: fixed
versions: + Python 3.8, - Python 3.5, Python 3.6, Python 3.7
2019-05-27 15:11:06vstinnersetnosy: + vstinner
messages: + msg343638
2017-03-10 21:50:35steve.dowersetstage: needs patch
type: behavior
versions: + Python 3.6, Python 3.7
2017-03-10 21:50:21steve.dowersetmessages: + msg289412
2017-03-10 14:23:36steve.dowersetmessages: + msg289364
2017-03-10 04:58:18Tibor Csonkacreate