bpo-29778: Ensure python3.dll is loaded from correct locations when P… · python/cpython@4981fe3

@@ -131,8 +131,6 @@ typedef struct {

131131

wchar_t *machine_path; /* from HKEY_LOCAL_MACHINE */

132132

wchar_t *user_path; /* from HKEY_CURRENT_USER */

133133134-

wchar_t *dll_path;

135-136134

const wchar_t *pythonpath_env;

137135

} PyCalculatePath;

138136

@@ -168,27 +166,37 @@ reduce(wchar_t *dir)

168166

static int

169167

change_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)) {

192200

dest[0] = '\0';

193201

return -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-492492

static PyStatus

493493

get_program_full_path(_PyPathConfig *pathconfig)

494494

{

@@ -669,19 +669,17 @@ static int

669669

get_pth_filename(PyCalculatePath *calculate, wchar_t *filename,

670670

const _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

}

686684

return 0;

687685

}

@@ -994,9 +992,12 @@ calculate_path(PyCalculatePath *calculate, _PyPathConfig *pathconfig)

994992

wchar_t zip_path[MAXPATHLEN+1];

995993

memset(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+

}

1000100110011002

calculate_home_prefix(calculate, argv0_path, zip_path, prefix);

10021003

@@ -1033,11 +1034,6 @@ calculate_init(PyCalculatePath *calculate, _PyPathConfig *pathconfig,

10331034

calculate->home = pathconfig->home;

10341035

calculate->path_env = _wgetenv(L"PATH");

103510361036-

calculate->dll_path = _Py_GetDLLPath();

1037-

if (calculate->dll_path == NULL) {

1038-

return _PyStatus_NO_MEMORY();

1039-

}

1040-10411037

calculate->pythonpath_env = config->pythonpath_env;

1042103810431039

return _PyStatus_OK();

@@ -1049,7 +1045,6 @@ calculate_free(PyCalculatePath *calculate)

10491045

{

10501046

PyMem_RawFree(calculate->machine_path);

10511047

PyMem_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

{

11151109

wchar_t py3path[MAXPATHLEN+1];

1116-

wchar_t *s;

11171110

if (python3_checked) {

11181111

return hPython3 != NULL;

11191112

}

11201113

python3_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);

11361129

if (hPython3 != NULL) {

11371130

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

11411135

wcscpy(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+

}

11441140

return hPython3 != NULL;

11451141

}