diff options
author | Steve Dower <steve.dower@microsoft.com> | 2018-02-22 18:39:26 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-02-22 18:39:26 (GMT) |
commit | 48e8c82fc63d2ddcddce8aa637a892839b551619 (patch) | |
tree | 37ad07f40dacd72bbd565fedbbefdd83d57cc4f7 /PC/getpathp.c | |
parent | 23ad6d0d1a7a6145a01494f4f3913a63d1f0250c (diff) | |
download | cpython-48e8c82fc63d2ddcddce8aa637a892839b551619.zip cpython-48e8c82fc63d2ddcddce8aa637a892839b551619.tar.gz cpython-48e8c82fc63d2ddcddce8aa637a892839b551619.tar.bz2 |
bpo-32457: Improves handling of denormalized executable path when launching Python (GH-5756)
Diffstat (limited to 'PC/getpathp.c')
-rw-r--r-- | PC/getpathp.c | 96 |
1 files changed, 42 insertions, 54 deletions
diff --git a/PC/getpathp.c b/PC/getpathp.c index e90a643..9382843 100644 --- a/PC/getpathp.c +++ b/PC/getpathp.c @@ -266,6 +266,41 @@ join(wchar_t *buffer, const wchar_t *stuff) } } +static int _PathCchCanonicalizeEx_Initialized = 0; +typedef HRESULT(__stdcall *PPathCchCanonicalizeEx) (PWSTR pszPathOut, size_t cchPathOut, + PCWSTR pszPathIn, unsigned long dwFlags); +static PPathCchCanonicalizeEx _PathCchCanonicalizeEx; + +static _PyInitError canonicalize(wchar_t *buffer, const wchar_t *path) +{ + if (buffer == NULL) { + return _Py_INIT_NO_MEMORY(); + } + + if (_PathCchCanonicalizeEx_Initialized == 0) { + HMODULE pathapi = LoadLibraryW(L"api-ms-win-core-path-l1-1-0.dll"); + if (pathapi) { + _PathCchCanonicalizeEx = (PPathCchCanonicalizeEx)GetProcAddress(pathapi, "PathCchCanonicalizeEx"); + } + else { + _PathCchCanonicalizeEx = NULL; + } + _PathCchCanonicalizeEx_Initialized = 1; + } + + if (_PathCchCanonicalizeEx) { + if (FAILED(_PathCchCanonicalizeEx(buffer, MAXPATHLEN + 1, path, 0))) { + return _Py_INIT_ERR("buffer overflow in getpathp.c's canonicalize()"); + } + } + else { + if (!PathCanonicalizeW(buffer, path)) { + return _Py_INIT_ERR("buffer overflow in getpathp.c's canonicalize()"); + } + } + return _Py_INIT_OK(); +} + /* gotlandmark only called by search_for_prefix, which ensures 'prefix' is null terminated in bounds. join() ensures @@ -504,63 +539,16 @@ get_program_full_path(const _PyCoreConfig *core_config, wchar_t program_full_path[MAXPATHLEN+1]; memset(program_full_path, 0, sizeof(program_full_path)); - if (GetModuleFileNameW(NULL, program_full_path, MAXPATHLEN)) { - goto done; - } - - /* If there is no slash in the argv0 path, then we have to - * assume python is on the user's $PATH, since there's no - * other way to find a directory to start the search from. If - * $PATH isn't exported, you lose. - */ -#ifdef ALTSEP - if (wcschr(core_config->program_name, SEP) || - wcschr(core_config->program_name, ALTSEP)) -#else - if (wcschr(core_config->program_name, SEP)) -#endif - { - wcsncpy(program_full_path, core_config->program_name, MAXPATHLEN); + if (!GetModuleFileNameW(NULL, program_full_path, MAXPATHLEN)) { + /* GetModuleFileName should never fail when passed NULL */ + return _Py_INIT_ERR("Cannot determine program path"); } - else if (calculate->path_env) { - const wchar_t *path = calculate->path_env; - while (1) { - const wchar_t *delim = wcschr(path, DELIM); - - if (delim) { - size_t len = delim - path; - /* ensure we can't overwrite buffer */ - len = min(MAXPATHLEN,len); - wcsncpy(program_full_path, path, len); - program_full_path[len] = '\0'; - } - else { - wcsncpy(program_full_path, path, MAXPATHLEN); - } - - /* join() is safe for MAXPATHLEN+1 size buffer */ - join(program_full_path, core_config->program_name); - if (exists(program_full_path)) { - break; - } - if (!delim) { - program_full_path[0] = '\0'; - break; - } - path = delim + 1; - } - } - else { - program_full_path[0] = '\0'; - } + config->program_full_path = PyMem_RawMalloc( + sizeof(wchar_t) * (MAXPATHLEN + 1)); -done: - config->program_full_path = _PyMem_RawWcsdup(program_full_path); - if (config->program_full_path == NULL) { - return _Py_INIT_NO_MEMORY(); - } - return _Py_INIT_OK(); + return canonicalize(config->program_full_path, + program_full_path); } |