◐ Shell
clean mode source ↗

[3.6] bpo-29778: Ensure python3.dll is loaded from correct locations when Python is embedded (GH-21298) by zooba · Pull Request #21354 · python/cpython

Expand Up @@ -118,7 +118,6 @@
static wchar_t prefix[MAXPATHLEN+1]; static wchar_t progpath[MAXPATHLEN+1]; static wchar_t dllpath[MAXPATHLEN+1]; static wchar_t *module_search_path = NULL;

Expand Down Expand Up @@ -150,24 +149,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 @@ -304,6 +316,20 @@ search_for_prefix(wchar_t *argv0_path, const wchar_t *landmark) return 0; }

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 @@ -467,15 +493,6 @@ get_progpath(void) wchar_t *path = _wgetenv(L"PATH"); wchar_t *prog = Py_GetProgramName();
#ifdef Py_ENABLE_SHARED extern HANDLE PyWin_DLLhModule; /* static init of progpath ensures final char remains \0 */ if (PyWin_DLLhModule) if (!GetModuleFileNameW(PyWin_DLLhModule, dllpath, MAXPATHLEN)) dllpath[0] = 0; #else dllpath[0] = 0; #endif if (GetModuleFileNameW(NULL, modulepath, MAXPATHLEN)) { canonicalize(progpath, modulepath); return; Expand Down Expand Up @@ -693,7 +710,7 @@ calculate_path(void) { wchar_t spbuffer[MAXPATHLEN+1];
if ((dllpath[0] && !change_ext(spbuffer, dllpath, L"._pth") && exists(spbuffer)) || if ((!get_dllpath(spbuffer) && !change_ext(spbuffer, spbuffer, L"._pth") && exists(spbuffer)) || (progpath[0] && !change_ext(spbuffer, progpath, L"._pth") && exists(spbuffer))) {
if (!read_pth_file(spbuffer, prefix, &Py_IsolatedFlag, &Py_NoSiteFlag)) { Expand Down Expand Up @@ -737,7 +754,11 @@ calculate_path(void) }
/* Calculate zip archive path from DLL or exe path */ change_ext(zip_path, dllpath[0] ? dllpath : progpath, L".zip"); if (!get_dllpath(zip_path)) { change_ext(zip_path, zip_path, L".zip"); } else { change_ext(zip_path, progpath, L".zip"); }
if (pythonhome == NULL || *pythonhome == '\0') { if (zip_path[0] && exists(zip_path)) { Expand Down Expand Up @@ -919,8 +940,6 @@ calculate_path(void) }

/* External interface */
void Py_SetPath(const wchar_t *path) { Expand Down Expand Up @@ -981,25 +1000,39 @@ int _Py_CheckPython3() { wchar_t py3path[MAXPATHLEN+1]; wchar_t *s; if (python3_checked) 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 */ wcscpy(py3path, dllpath); s = wcsrchr(py3path, L'\\'); if (!s) s = py3path; wcscpy(s, L"\\python3.dll"); hPython3 = LoadLibraryExW(py3path, NULL, LOAD_WITH_ALTERED_SEARCH_PATH); if (hPython3 != NULL) return 1; use that DLL */ if (!get_dllpath(py3path)) { reduce(py3path); join(py3path, PY3_DLLNAME); hPython3 = LoadLibraryExW(py3path, NULL, LOAD_WITH_ALTERED_SEARCH_PATH); if (hPython3 != NULL) { return 1; } }
/* If we can locate python3.dll in our application dir, use that DLL */ wcscpy(py3path, Py_GetPrefix()); if (py3path[0]) { join(py3path, PY3_DLLNAME); hPython3 = LoadLibraryExW(py3path, NULL, LOAD_WITH_ALTERED_SEARCH_PATH); 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_WITH_ALTERED_SEARCH_PATH); } return hPython3 != NULL; }