◐ Shell
clean mode source ↗

[3.9] bpo-29778: Ensure python3.dll is loaded from correct locations when Python is embedded (GH-21297) by miss-islington · Pull Request #21351 · python/cpython

Expand Up @@ -131,8 +131,6 @@ typedef struct { wchar_t *machine_path; /* from HKEY_LOCAL_MACHINE */ wchar_t *user_path; /* from HKEY_CURRENT_USER */
wchar_t *dll_path;
const wchar_t *pythonpath_env; } PyCalculatePath;
Expand Down Expand Up @@ -168,27 +166,37 @@ reduce(wchar_t *dir) static int change_ext(wchar_t *dest, const wchar_t *src, const wchar_t *ext) { size_t src_len = wcsnlen_s(src, MAXPATHLEN+1); size_t i = src_len; if (i >= MAXPATHLEN+1) { Py_FatalError("buffer overflow in getpathp.c's reduce()"); } if (src && src != dest) { size_t src_len = wcsnlen_s(src, MAXPATHLEN+1); size_t i = src_len; if (i >= MAXPATHLEN+1) { Py_FatalError("buffer overflow in getpathp.c's reduce()"); }
while (i > 0 && src[i] != '.' && !is_sep(src[i])) --i; while (i > 0 && src[i] != '.' && !is_sep(src[i])) --i;
if (i == 0) { dest[0] = '\0'; return -1; } if (i == 0) { dest[0] = '\0'; return -1; }
if (is_sep(src[i])) { i = src_len; }
if (is_sep(src[i])) { i = src_len; if (wcsncpy_s(dest, MAXPATHLEN+1, src, i)) { dest[0] = '\0'; return -1; } } else { wchar_t *s = wcsrchr(dest, L'.'); if (s) { s[0] = '\0'; } }
if (wcsncpy_s(dest, MAXPATHLEN+1, src, i) || wcscat_s(dest, MAXPATHLEN+1, ext)) { if (wcscat_s(dest, MAXPATHLEN+1, ext)) { dest[0] = '\0'; return -1; } Expand Down Expand Up @@ -297,6 +305,19 @@ search_for_prefix(wchar_t *prefix, const wchar_t *argv0_path, const wchar_t *lan }

static int get_dllpath(wchar_t *dllpath) { #ifdef Py_ENABLE_SHARED extern HANDLE PyWin_DLLhModule; if (PyWin_DLLhModule && GetModuleFileNameW(PyWin_DLLhModule, dllpath, MAXPATHLEN)) { return 0; } #endif return -1; }

#ifdef Py_ENABLE_SHARED
/* a string loaded from the DLL at startup.*/ Expand Down Expand Up @@ -468,27 +489,6 @@ getpythonregpath(HKEY keyBase, int skipcore) #endif /* Py_ENABLE_SHARED */

wchar_t* _Py_GetDLLPath(void) { wchar_t dll_path[MAXPATHLEN+1]; memset(dll_path, 0, sizeof(dll_path));
#ifdef Py_ENABLE_SHARED extern HANDLE PyWin_DLLhModule; if (PyWin_DLLhModule) { if (!GetModuleFileNameW(PyWin_DLLhModule, dll_path, MAXPATHLEN)) { dll_path[0] = 0; } } #else dll_path[0] = 0; #endif
return _PyMem_RawWcsdup(dll_path); }

static PyStatus get_program_full_path(_PyPathConfig *pathconfig) { Expand Down Expand Up @@ -669,19 +669,17 @@ static int get_pth_filename(PyCalculatePath *calculate, wchar_t *filename, const _PyPathConfig *pathconfig) { if (calculate->dll_path[0]) { if (!change_ext(filename, calculate->dll_path, L"._pth") && exists(filename)) { return 1; } if (get_dllpath(filename) && !change_ext(filename, filename, L"._pth") && exists(filename)) { return 1; } if (pathconfig->program_full_path[0]) { if (!change_ext(filename, pathconfig->program_full_path, L"._pth") && exists(filename)) { return 1; } if (pathconfig->program_full_path[0] && !change_ext(filename, pathconfig->program_full_path, L"._pth") && exists(filename)) { return 1; } return 0; } Expand Down Expand Up @@ -994,9 +992,12 @@ calculate_path(PyCalculatePath *calculate, _PyPathConfig *pathconfig) wchar_t zip_path[MAXPATHLEN+1]; memset(zip_path, 0, sizeof(zip_path));
change_ext(zip_path, calculate->dll_path[0] ? calculate->dll_path : pathconfig->program_full_path, L".zip"); if (get_dllpath(zip_path) || change_ext(zip_path, zip_path, L".zip")) { if (change_ext(zip_path, pathconfig->program_full_path, L".zip")) { zip_path[0] = L'\0'; } }
calculate_home_prefix(calculate, argv0_path, zip_path, prefix);
Expand Down Expand Up @@ -1033,11 +1034,6 @@ calculate_init(PyCalculatePath *calculate, _PyPathConfig *pathconfig, calculate->home = pathconfig->home; calculate->path_env = _wgetenv(L"PATH");
calculate->dll_path = _Py_GetDLLPath(); if (calculate->dll_path == NULL) { return _PyStatus_NO_MEMORY(); }
calculate->pythonpath_env = config->pythonpath_env;
return _PyStatus_OK(); Expand All @@ -1049,7 +1045,6 @@ calculate_free(PyCalculatePath *calculate) { PyMem_RawFree(calculate->machine_path); PyMem_RawFree(calculate->user_path); PyMem_RawFree(calculate->dll_path); }

Expand All @@ -1059,7 +1054,6 @@ calculate_free(PyCalculatePath *calculate)
- PyConfig.pythonpath_env: PYTHONPATH environment variable - _PyPathConfig.home: Py_SetPythonHome() or PYTHONHOME environment variable - DLL path: _Py_GetDLLPath() - PATH environment variable - __PYVENV_LAUNCHER__ environment variable - GetModuleFileNameW(NULL): fully qualified path of the executable file of Expand Down Expand Up @@ -1113,33 +1107,35 @@ int _Py_CheckPython3(void) { wchar_t py3path[MAXPATHLEN+1]; wchar_t *s; if (python3_checked) { return hPython3 != NULL; } python3_checked = 1;
/* If there is a python3.dll next to the python3y.dll, assume this is a build tree; use that DLL */ if (_Py_dll_path != NULL) { wcscpy(py3path, _Py_dll_path); } else { wcscpy(py3path, L""); } s = wcsrchr(py3path, L'\\'); if (!s) { s = py3path; use that DLL */ if (!get_dllpath(py3path)) { reduce(py3path); join(py3path, PY3_DLLNAME); hPython3 = LoadLibraryExW(py3path, NULL, LOAD_LIBRARY_SEARCH_DEFAULT_DIRS); if (hPython3 != NULL) { return 1; } } wcscpy(s, L"\\python3.dll"); hPython3 = LoadLibraryExW(py3path, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
/* If we can locate python3.dll in our application dir, use that DLL */ hPython3 = LoadLibraryExW(PY3_DLLNAME, NULL, LOAD_LIBRARY_SEARCH_APPLICATION_DIR); if (hPython3 != NULL) { return 1; }
/* Check sys.prefix\DLLs\python3.dll */ /* For back-compat, also search {sys.prefix}\DLLs, though that has not been a normal install layout for a while */ wcscpy(py3path, Py_GetPrefix()); wcscat(py3path, L"\\DLLs\\python3.dll"); hPython3 = LoadLibraryExW(py3path, NULL, LOAD_WITH_ALTERED_SEARCH_PATH); if (py3path[0]) { join(py3path, L"DLLs\\" PY3_DLLNAME); hPython3 = LoadLibraryExW(py3path, NULL, LOAD_LIBRARY_SEARCH_DEFAULT_DIRS); } return hPython3 != NULL; }