From: Miss Islington (bot) <31488909+miss-islington@users.noreply.github.com> Date: Thu, 22 Apr 2021 20:07:02 +0000 (-0700) Subject: bpo-38822: Fixed os.stat failing on inaccessible directories. (GH-25527) X-Git-Tag: v3.8.10~49 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=400bd9a3858ea28ea264682b7f050c69638b1ff1;p=thirdparty%2FPython%2Fcpython.git bpo-38822: Fixed os.stat failing on inaccessible directories. (GH-25527) It would just fail if the path was inaccessible and had a trailing slash. It should fall back to the parent directory's metadata. (cherry picked from commit fe63a401a9b3ca1751b81b5d6ddb2beb7f3675c1) Co-authored-by: Steve Dower --- diff --git a/Misc/NEWS.d/next/Windows/2021-04-22-19-49-20.bpo-38822.jgdPmq.rst b/Misc/NEWS.d/next/Windows/2021-04-22-19-49-20.bpo-38822.jgdPmq.rst new file mode 100644 index 000000000000..072a96989c3d --- /dev/null +++ b/Misc/NEWS.d/next/Windows/2021-04-22-19-49-20.bpo-38822.jgdPmq.rst @@ -0,0 +1,3 @@ +Fixed :func:`os.stat` failing on inaccessible directories with a trailing +slash, rather than falling back to the parent directory's metadata. This +implicitly affected :func:`os.path.exists` and :func:`os.path.isdir`. diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index 0ef75fa4486f..e821f1a59bde 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -1651,9 +1651,28 @@ attributes_from_dir(LPCWSTR pszFile, BY_HANDLE_FILE_INFORMATION *info, ULONG *re { HANDLE hFindFile; WIN32_FIND_DATAW FileData; - hFindFile = FindFirstFileW(pszFile, &FileData); - if (hFindFile == INVALID_HANDLE_VALUE) + LPCWSTR filename = pszFile; + size_t n = wcslen(pszFile); + if (n && (pszFile[n - 1] == L'\\' || pszFile[n - 1] == L'/')) { + // cannot use PyMem_Malloc here because we do not hold the GIL + filename = (LPCWSTR)malloc((n + 1) * sizeof(filename[0])); + wcsncpy_s((LPWSTR)filename, n + 1, pszFile, n); + while (--n > 0 && (filename[n] == L'\\' || filename[n] == L'/')) { + ((LPWSTR)filename)[n] = L'\0'; + } + if (!n || filename[n] == L':') { + // Nothing left te query + free((void *)filename); + return FALSE; + } + } + hFindFile = FindFirstFileW(filename, &FileData); + if (pszFile != filename) { + free((void *)filename); + } + if (hFindFile == INVALID_HANDLE_VALUE) { return FALSE; + } FindClose(hFindFile); find_data_to_file_info(&FileData, info, reparse_tag); return TRUE;