From f482aa3551d169b3f2aa98b0656be3a9c07cb917 Mon Sep 17 00:00:00 2001 From: Steve Dower Date: Tue, 5 Oct 2021 12:42:15 +0100 Subject: [PATCH 1/3] bpo-45375: Fix assertion failure due to searching for stdlib in unnormalised paths --- .../2021-10-05-12-41-53.bpo-45375.CohPP-.rst | 2 ++ PC/getpathp.c | 20 ++++++++++++++++++- 2 files changed, 21 insertions(+), 1 deletion(-) create mode 100644 Misc/NEWS.d/next/Windows/2021-10-05-12-41-53.bpo-45375.CohPP-.rst diff --git a/Misc/NEWS.d/next/Windows/2021-10-05-12-41-53.bpo-45375.CohPP-.rst b/Misc/NEWS.d/next/Windows/2021-10-05-12-41-53.bpo-45375.CohPP-.rst new file mode 100644 index 000000000000000..c72164373abe6b6 --- /dev/null +++ b/Misc/NEWS.d/next/Windows/2021-10-05-12-41-53.bpo-45375.CohPP-.rst @@ -0,0 +1,2 @@ +Fixes an assertion failure due to searching for the standard library in +unnormalised paths. diff --git a/PC/getpathp.c b/PC/getpathp.c index 16bb4997f819b7f..ad9e6dc69f8eb3d 100644 --- a/PC/getpathp.c +++ b/PC/getpathp.c @@ -265,7 +265,21 @@ canonicalize(wchar_t *buffer, const wchar_t *path) return _PyStatus_NO_MEMORY(); } - if (FAILED(PathCchCanonicalizeEx(buffer, MAXPATHLEN + 1, path, 0))) { + if (PathIsRelativeW(path)) { + wchar_t cwd[MAXPATHLEN]; + if (!GetCurrentDirectoryW(MAXPATHLEN, cwd)) { + return _PyStatus_ERR("unable to find current working directory"); + } + if (FAILED(PathCchCombineEx(buffer, MAXPATHLEN + 1, cwd, path, PATHCCH_ALLOW_LONG_PATHS))) { + return INIT_ERR_BUFFER_OVERFLOW(); + } + if (FAILED(PathCchCanonicalizeEx(buffer, MAXPATHLEN + 1, buffer, PATHCCH_ALLOW_LONG_PATHS))) { + return INIT_ERR_BUFFER_OVERFLOW(); + } + return _PyStatus_OK(); + } + + if (FAILED(PathCchCanonicalizeEx(buffer, MAXPATHLEN + 1, path, PATHCCH_ALLOW_LONG_PATHS))) { return INIT_ERR_BUFFER_OVERFLOW(); } return _PyStatus_OK(); @@ -291,6 +305,9 @@ search_for_prefix(wchar_t *prefix, const wchar_t *argv0_path) /* Search from argv0_path, until LANDMARK is found. We guarantee 'prefix' is null terminated in bounds. */ wcscpy_s(prefix, MAXPATHLEN+1, argv0_path); + if (!prefix[0]) { + return 0; + } wchar_t stdlibdir[MAXPATHLEN+1]; wcscpy_s(stdlibdir, Py_ARRAY_LENGTH(stdlibdir), prefix); /* We initialize with the longest possible path, in case it doesn't fit. @@ -938,6 +955,7 @@ calculate_module_search_path(PyCalculatePath *calculate, look--; nchars = lookEnd-look; wcsncpy(lookBuf, look+1, nchars); + canonicalize(lookBuf, lookBuf); lookBuf[nchars] = L'\0'; /* Up one level to the parent */ reduce(lookBuf); From e3d3672027d48eb34163a2e5d85c810a988361aa Mon Sep 17 00:00:00 2001 From: Steve Dower Date: Tue, 5 Oct 2021 12:51:25 +0100 Subject: [PATCH 2/3] Ensure freshly-built Python is run correctly --- PCbuild/regen.targets | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/PCbuild/regen.targets b/PCbuild/regen.targets index 9492cff2d8c3eaa..c0bde1ec6ba5115 100644 --- a/PCbuild/regen.targets +++ b/PCbuild/regen.targets @@ -104,7 +104,9 @@ Condition="($(Platform) == 'Win32' or $(Platform) == 'x64') and $(Configuration) != 'PGInstrument' and $(Configuration) != 'PGUpdate'"> - From 468eda78a5e74726fe7c02ef90412814a445a096 Mon Sep 17 00:00:00 2001 From: Steve Dower Date: Tue, 5 Oct 2021 13:05:31 +0100 Subject: [PATCH 3/3] Fix path calculation --- PC/getpathp.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/PC/getpathp.c b/PC/getpathp.c index ad9e6dc69f8eb3d..98a754976c67086 100644 --- a/PC/getpathp.c +++ b/PC/getpathp.c @@ -266,14 +266,14 @@ canonicalize(wchar_t *buffer, const wchar_t *path) } if (PathIsRelativeW(path)) { - wchar_t cwd[MAXPATHLEN]; - if (!GetCurrentDirectoryW(MAXPATHLEN, cwd)) { + wchar_t buff[MAXPATHLEN]; + if (!GetCurrentDirectoryW(MAXPATHLEN, buff)) { return _PyStatus_ERR("unable to find current working directory"); } - if (FAILED(PathCchCombineEx(buffer, MAXPATHLEN + 1, cwd, path, PATHCCH_ALLOW_LONG_PATHS))) { + if (FAILED(PathCchCombineEx(buff, MAXPATHLEN + 1, buff, path, PATHCCH_ALLOW_LONG_PATHS))) { return INIT_ERR_BUFFER_OVERFLOW(); } - if (FAILED(PathCchCanonicalizeEx(buffer, MAXPATHLEN + 1, buffer, PATHCCH_ALLOW_LONG_PATHS))) { + if (FAILED(PathCchCanonicalizeEx(buffer, MAXPATHLEN + 1, buff, PATHCCH_ALLOW_LONG_PATHS))) { return INIT_ERR_BUFFER_OVERFLOW(); } return _PyStatus_OK(); @@ -942,6 +942,7 @@ calculate_module_search_path(PyCalculatePath *calculate, the parent of that. */ if (prefix[0] == L'\0') { + PyStatus status; wchar_t lookBuf[MAXPATHLEN+1]; const wchar_t *look = buf - 1; /* 'buf' is at the end of the buffer */ while (1) { @@ -955,8 +956,11 @@ calculate_module_search_path(PyCalculatePath *calculate, look--; nchars = lookEnd-look; wcsncpy(lookBuf, look+1, nchars); - canonicalize(lookBuf, lookBuf); lookBuf[nchars] = L'\0'; + status = canonicalize(lookBuf, lookBuf); + if (_PyStatus_EXCEPTION(status)) { + return status; + } /* Up one level to the parent */ reduce(lookBuf); if (search_for_prefix(prefix, lookBuf)) {