bpo-29778: Ensure python3.dll is loaded from correct locations when P… · python/cpython@4981fe3
@@ -131,8 +131,6 @@ typedef struct {
131131wchar_t *machine_path; /* from HKEY_LOCAL_MACHINE */
132132wchar_t *user_path; /* from HKEY_CURRENT_USER */
133133134-wchar_t *dll_path;
135-136134const wchar_t *pythonpath_env;
137135} PyCalculatePath;
138136@@ -168,27 +166,37 @@ reduce(wchar_t *dir)
168166static int
169167change_ext(wchar_t *dest, const wchar_t *src, const wchar_t *ext)
170168{
171-size_t src_len = wcsnlen_s(src, MAXPATHLEN+1);
172-size_t i = src_len;
173-if (i >= MAXPATHLEN+1) {
174-Py_FatalError("buffer overflow in getpathp.c's reduce()");
175- }
169+if (src && src != dest) {
170+size_t src_len = wcsnlen_s(src, MAXPATHLEN+1);
171+size_t i = src_len;
172+if (i >= MAXPATHLEN+1) {
173+Py_FatalError("buffer overflow in getpathp.c's reduce()");
174+ }
176175177-while (i > 0 && src[i] != '.' && !is_sep(src[i]))
178---i;
176+ while (i > 0 && src[i] != '.' && !is_sep(src[i]))
177+ --i;
179178180-if (i == 0) {
181-dest[0] = '\0';
182-return -1;
183- }
179+if (i == 0) {
180+dest[0] = '\0';
181+return -1;
182+ }
183+184+if (is_sep(src[i])) {
185+i = src_len;
186+ }
184187185-if (is_sep(src[i])) {
186-i = src_len;
188+if (wcsncpy_s(dest, MAXPATHLEN+1, src, i)) {
189+dest[0] = '\0';
190+return -1;
191+ }
192+ } else {
193+wchar_t *s = wcsrchr(dest, L'.');
194+if (s) {
195+s[0] = '\0';
196+ }
187197 }
188198189-if (wcsncpy_s(dest, MAXPATHLEN+1, src, i) ||
190-wcscat_s(dest, MAXPATHLEN+1, ext))
191- {
199+if (wcscat_s(dest, MAXPATHLEN+1, ext)) {
192200dest[0] = '\0';
193201return -1;
194202 }
@@ -297,6 +305,19 @@ search_for_prefix(wchar_t *prefix, const wchar_t *argv0_path, const wchar_t *lan
297305}
298306299307308+static int
309+get_dllpath(wchar_t *dllpath)
310+{
311+#ifdef Py_ENABLE_SHARED
312+extern HANDLE PyWin_DLLhModule;
313+if (PyWin_DLLhModule && GetModuleFileNameW(PyWin_DLLhModule, dllpath, MAXPATHLEN)) {
314+return 0;
315+ }
316+#endif
317+return -1;
318+}
319+320+300321#ifdef Py_ENABLE_SHARED
301322302323/* a string loaded from the DLL at startup.*/
@@ -468,27 +489,6 @@ getpythonregpath(HKEY keyBase, int skipcore)
468489#endif /* Py_ENABLE_SHARED */
469490470491471-wchar_t*
472-_Py_GetDLLPath(void)
473-{
474-wchar_t dll_path[MAXPATHLEN+1];
475-memset(dll_path, 0, sizeof(dll_path));
476-477-#ifdef Py_ENABLE_SHARED
478-extern HANDLE PyWin_DLLhModule;
479-if (PyWin_DLLhModule) {
480-if (!GetModuleFileNameW(PyWin_DLLhModule, dll_path, MAXPATHLEN)) {
481-dll_path[0] = 0;
482- }
483- }
484-#else
485-dll_path[0] = 0;
486-#endif
487-488-return _PyMem_RawWcsdup(dll_path);
489-}
490-491-492492static PyStatus
493493get_program_full_path(_PyPathConfig *pathconfig)
494494{
@@ -669,19 +669,17 @@ static int
669669get_pth_filename(PyCalculatePath *calculate, wchar_t *filename,
670670const _PyPathConfig *pathconfig)
671671{
672-if (calculate->dll_path[0]) {
673-if (!change_ext(filename, calculate->dll_path, L"._pth") &&
674-exists(filename))
675- {
676-return 1;
677- }
672+if (get_dllpath(filename) &&
673+ !change_ext(filename, filename, L"._pth") &&
674+exists(filename))
675+ {
676+return 1;
678677 }
679-if (pathconfig->program_full_path[0]) {
680-if (!change_ext(filename, pathconfig->program_full_path, L"._pth") &&
681-exists(filename))
682- {
683-return 1;
684- }
678+if (pathconfig->program_full_path[0] &&
679+ !change_ext(filename, pathconfig->program_full_path, L"._pth") &&
680+exists(filename))
681+ {
682+return 1;
685683 }
686684return 0;
687685}
@@ -994,9 +992,12 @@ calculate_path(PyCalculatePath *calculate, _PyPathConfig *pathconfig)
994992wchar_t zip_path[MAXPATHLEN+1];
995993memset(zip_path, 0, sizeof(zip_path));
996994997-change_ext(zip_path,
998-calculate->dll_path[0] ? calculate->dll_path : pathconfig->program_full_path,
999-L".zip");
995+if (get_dllpath(zip_path) || change_ext(zip_path, zip_path, L".zip"))
996+ {
997+if (change_ext(zip_path, pathconfig->program_full_path, L".zip")) {
998+zip_path[0] = L'\0';
999+ }
1000+ }
1000100110011002calculate_home_prefix(calculate, argv0_path, zip_path, prefix);
10021003@@ -1033,11 +1034,6 @@ calculate_init(PyCalculatePath *calculate, _PyPathConfig *pathconfig,
10331034calculate->home = pathconfig->home;
10341035calculate->path_env = _wgetenv(L"PATH");
103510361036-calculate->dll_path = _Py_GetDLLPath();
1037-if (calculate->dll_path == NULL) {
1038-return _PyStatus_NO_MEMORY();
1039- }
1040-10411037calculate->pythonpath_env = config->pythonpath_env;
1042103810431039return _PyStatus_OK();
@@ -1049,7 +1045,6 @@ calculate_free(PyCalculatePath *calculate)
10491045{
10501046PyMem_RawFree(calculate->machine_path);
10511047PyMem_RawFree(calculate->user_path);
1052-PyMem_RawFree(calculate->dll_path);
10531048}
1054104910551050@@ -1059,7 +1054,6 @@ calculate_free(PyCalculatePath *calculate)
1059105410601055 - PyConfig.pythonpath_env: PYTHONPATH environment variable
10611056 - _PyPathConfig.home: Py_SetPythonHome() or PYTHONHOME environment variable
1062- - DLL path: _Py_GetDLLPath()
10631057 - PATH environment variable
10641058 - __PYVENV_LAUNCHER__ environment variable
10651059 - GetModuleFileNameW(NULL): fully qualified path of the executable file of
@@ -1113,33 +1107,35 @@ int
11131107_Py_CheckPython3(void)
11141108{
11151109wchar_t py3path[MAXPATHLEN+1];
1116-wchar_t *s;
11171110if (python3_checked) {
11181111return hPython3 != NULL;
11191112 }
11201113python3_checked = 1;
1121111411221115/* If there is a python3.dll next to the python3y.dll,
1123- assume this is a build tree; use that DLL */
1124-if (_Py_dll_path != NULL) {
1125-wcscpy(py3path, _Py_dll_path);
1126- }
1127-else {
1128-wcscpy(py3path, L"");
1129- }
1130-s = wcsrchr(py3path, L'\\');
1131-if (!s) {
1132-s = py3path;
1116+ use that DLL */
1117+if (!get_dllpath(py3path)) {
1118+reduce(py3path);
1119+join(py3path, PY3_DLLNAME);
1120+hPython3 = LoadLibraryExW(py3path, NULL, LOAD_LIBRARY_SEARCH_DEFAULT_DIRS);
1121+if (hPython3 != NULL) {
1122+return 1;
1123+ }
11331124 }
1134-wcscpy(s, L"\\python3.dll");
1135-hPython3 = LoadLibraryExW(py3path, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
1125+1126+/* If we can locate python3.dll in our application dir,
1127+ use that DLL */
1128+hPython3 = LoadLibraryExW(PY3_DLLNAME, NULL, LOAD_LIBRARY_SEARCH_APPLICATION_DIR);
11361129if (hPython3 != NULL) {
11371130return 1;
11381131 }
113911321140-/* Check sys.prefix\DLLs\python3.dll */
1133+/* For back-compat, also search {sys.prefix}\DLLs, though
1134+ that has not been a normal install layout for a while */
11411135wcscpy(py3path, Py_GetPrefix());
1142-wcscat(py3path, L"\\DLLs\\python3.dll");
1143-hPython3 = LoadLibraryExW(py3path, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
1136+if (py3path[0]) {
1137+join(py3path, L"DLLs\\" PY3_DLLNAME);
1138+hPython3 = LoadLibraryExW(py3path, NULL, LOAD_LIBRARY_SEARCH_DEFAULT_DIRS);
1139+ }
11441140return hPython3 != NULL;
11451141}