Skip to content

Commit 400bd9a

Browse files
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 fe63a40) Co-authored-by: Steve Dower <[email protected]>
1 parent ef63328 commit 400bd9a

File tree

2 files changed

+24
-2
lines changed

2 files changed

+24
-2
lines changed
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Fixed :func:`os.stat` failing on inaccessible directories with a trailing
2+
slash, rather than falling back to the parent directory's metadata. This
3+
implicitly affected :func:`os.path.exists` and :func:`os.path.isdir`.

Modules/posixmodule.c

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1651,9 +1651,28 @@ attributes_from_dir(LPCWSTR pszFile, BY_HANDLE_FILE_INFORMATION *info, ULONG *re
16511651
{
16521652
HANDLE hFindFile;
16531653
WIN32_FIND_DATAW FileData;
1654-
hFindFile = FindFirstFileW(pszFile, &FileData);
1655-
if (hFindFile == INVALID_HANDLE_VALUE)
1654+
LPCWSTR filename = pszFile;
1655+
size_t n = wcslen(pszFile);
1656+
if (n && (pszFile[n - 1] == L'\\' || pszFile[n - 1] == L'/')) {
1657+
// cannot use PyMem_Malloc here because we do not hold the GIL
1658+
filename = (LPCWSTR)malloc((n + 1) * sizeof(filename[0]));
1659+
wcsncpy_s((LPWSTR)filename, n + 1, pszFile, n);
1660+
while (--n > 0 && (filename[n] == L'\\' || filename[n] == L'/')) {
1661+
((LPWSTR)filename)[n] = L'\0';
1662+
}
1663+
if (!n || filename[n] == L':') {
1664+
// Nothing left te query
1665+
free((void *)filename);
1666+
return FALSE;
1667+
}
1668+
}
1669+
hFindFile = FindFirstFileW(filename, &FileData);
1670+
if (pszFile != filename) {
1671+
free((void *)filename);
1672+
}
1673+
if (hFindFile == INVALID_HANDLE_VALUE) {
16561674
return FALSE;
1675+
}
16571676
FindClose(hFindFile);
16581677
find_data_to_file_info(&FileData, info, reparse_tag);
16591678
return TRUE;

0 commit comments

Comments
 (0)