summaryrefslogtreecommitdiffstats
path: root/PC/getpathp.c
diff options
context:
space:
mode:
authorSteve Dower <steve.dower@python.org>2020-07-06 16:32:00 (GMT)
committerGitHub <noreply@github.com>2020-07-06 16:32:00 (GMT)
commitdcbaa1b49cd9062fb9ba2b9d49555ac6cd8c60b5 (patch)
tree4b1d3d5130de1db92de3240f4decc656ee7247ef /PC/getpathp.c
parentdeb016224cc506503fb05e821a60158c83918ed4 (diff)
downloadcpython-dcbaa1b49cd9062fb9ba2b9d49555ac6cd8c60b5.zip
cpython-dcbaa1b49cd9062fb9ba2b9d49555ac6cd8c60b5.tar.gz
cpython-dcbaa1b49cd9062fb9ba2b9d49555ac6cd8c60b5.tar.bz2
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
Diffstat (limited to 'PC/getpathp.c')
-rw-r--r--PC/getpathp.c150
1 files changed, 73 insertions, 77 deletions
diff --git a/PC/getpathp.c b/PC/getpathp.c
index fd5cfa7..0939c5f 100644
--- a/PC/getpathp.c
+++ b/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;
+ 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;
}
@@ -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);
- }
- 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;
}