mirror of
https://github.com/python/cpython.git
synced 2025-08-03 00:23:06 +00:00
bpo-29778: Ensure python3.dll is loaded from correct locations when Python is embedded (GH-21297)
Also enables using debug build of `python3_d.dll` Reference: CVE-2020-15523
This commit is contained in:
parent
deb016224c
commit
dcbaa1b49c
8 changed files with 150 additions and 137 deletions
156
PC/getpathp.c
156
PC/getpathp.c
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
||||
if (i == 0) {
|
||||
dest[0] = '\0';
|
||||
return -1;
|
||||
}
|
||||
|
||||
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';
|
||||
}
|
||||
}
|
||||
|
||||
while (i > 0 && src[i] != '.' && !is_sep(src[i]))
|
||||
--i;
|
||||
|
||||
if (i == 0) {
|
||||
dest[0] = '\0';
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (is_sep(src[i])) {
|
||||
i = src_len;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
@ -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.*/
|
||||
|
@ -468,27 +489,6 @@ done:
|
|||
#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)
|
||||
{
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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();
|
||||
|
@ -1049,7 +1045,6 @@ calculate_free(PyCalculatePath *calculate)
|
|||
{
|
||||
PyMem_RawFree(calculate->machine_path);
|
||||
PyMem_RawFree(calculate->user_path);
|
||||
PyMem_RawFree(calculate->dll_path);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
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;
|
||||
}
|
||||
}
|
||||
else {
|
||||
wcscpy(py3path, L"");
|
||||
}
|
||||
s = wcsrchr(py3path, L'\\');
|
||||
if (!s) {
|
||||
s = py3path;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue