Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 0b4dc48

Browse files
committed
Issue #28075: Check for ERROR_ACCESS_DENIED in Windows implementation of os.stat()
Patch by Eryk Sun.
1 parent 6d57fe1 commit 0b4dc48

3 files changed

Lines changed: 26 additions & 2 deletions

File tree

Lib/test/test_os.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -432,6 +432,25 @@ def test_file_attributes(self):
432432
result.st_file_attributes & stat.FILE_ATTRIBUTE_DIRECTORY,
433433
stat.FILE_ATTRIBUTE_DIRECTORY)
434434

435+
@unittest.skipUnless(sys.platform == "win32", "Win32 specific tests")
436+
def test_access_denied(self):
437+
# Default to FindFirstFile WIN32_FIND_DATA when access is
438+
# denied. See issue 28075.
439+
# os.environ['TEMP'] should be located on a volume that
440+
# supports file ACLs.
441+
fname = os.path.join(os.environ['TEMP'], self.fname)
442+
self.addCleanup(support.unlink, fname)
443+
create_file(fname, b'ABC')
444+
# Deny the right to [S]YNCHRONIZE on the file to
445+
# force CreateFile to fail with ERROR_ACCESS_DENIED.
446+
DETACHED_PROCESS = 8
447+
subprocess.check_call(
448+
['icacls.exe', fname, '/deny', 'Users:(S)'],
449+
creationflags=DETACHED_PROCESS
450+
)
451+
result = os.stat(fname)
452+
self.assertNotEqual(result.st_size, 0)
453+
435454

436455
class UtimeTests(unittest.TestCase):
437456
def setUp(self):

Misc/NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,9 @@ Core and Builtins
7171
Library
7272
-------
7373

74+
- Issue #28075: Check for ERROR_ACCESS_DENIED in Windows implementation of
75+
os.stat(). Patch by Eryk Sun.
76+
7477
- Issue #25270: Prevent codecs.escape_encode() from raising SystemError when
7578
an empty bytestring is passed.
7679

Modules/posixmodule.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1515,7 +1515,9 @@ win32_xstat_impl(const char *path, struct _Py_stat_struct *result,
15151515
/* Either the target doesn't exist, or we don't have access to
15161516
get a handle to it. If the former, we need to return an error.
15171517
If the latter, we can use attributes_from_dir. */
1518-
if (GetLastError() != ERROR_SHARING_VIOLATION)
1518+
DWORD lastError = GetLastError();
1519+
if (lastError != ERROR_ACCESS_DENIED &&
1520+
lastError != ERROR_SHARING_VIOLATION)
15191521
return -1;
15201522
/* Could not get attributes on open file. Fall back to
15211523
reading the directory. */
@@ -1525,7 +1527,7 @@ win32_xstat_impl(const char *path, struct _Py_stat_struct *result,
15251527
if (info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
15261528
if (traverse) {
15271529
/* Should traverse, but could not open reparse point handle */
1528-
SetLastError(ERROR_SHARING_VIOLATION);
1530+
SetLastError(lastError);
15291531
return -1;
15301532
}
15311533
}

0 commit comments

Comments
 (0)