pFad - Phone/Frame/Anonymizer/Declutterfier! Saves Data!


--- a PPN by Garber Painting Akron. With Image Size Reduction included!

URL: http://github.com/python/cpython/commit/ed066481c76c6888ff5709f5b9f93b92c232a4a6

097560d244c08.css" /> gh-111877: Fixes stat() handling for inaccessible files on Windows (G… · python/cpython@ed06648 · GitHub
Skip to content

Commit ed06648

Browse files
authored
gh-111877: Fixes stat() handling for inaccessible files on Windows (GH-113716)
1 parent e68806c commit ed06648

File tree

3 files changed

+72
-6
lines changed

3 files changed

+72
-6
lines changed

Lib/test/test_os.py

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3085,6 +3085,66 @@ def test_stat_unlink_race(self):
30853085
except subprocess.TimeoutExpired:
30863086
proc.terminate()
30873087

3088+
@support.requires_subprocess()
3089+
def test_stat_inaccessible_file(self):
3090+
filename = os_helper.TESTFN
3091+
ICACLS = os.path.expandvars(r"%SystemRoot%\System32\icacls.exe")
3092+
3093+
with open(filename, "wb") as f:
3094+
f.write(b'Test data')
3095+
3096+
stat1 = os.stat(filename)
3097+
3098+
try:
3099+
# Remove all permissions from the file
3100+
subprocess.check_output([ICACLS, filename, "/inheritance:r"],
3101+
stderr=subprocess.STDOUT)
3102+
except subprocess.CalledProcessError as ex:
3103+
if support.verbose:
3104+
print(ICACLS, filename, "/inheritance:r", "failed.")
3105+
print(ex.stdout.decode("oem", "replace").rstrip())
3106+
try:
3107+
os.unlink(filename)
3108+
except OSError:
3109+
pass
3110+
self.skipTest("Unable to create inaccessible file")
3111+
3112+
def cleanup():
3113+
# Give delete permission. We are the file owner, so we can do this
3114+
# even though we removed all permissions earlier.
3115+
subprocess.check_output([ICACLS, filename, "/grant", "Everyone:(D)"],
3116+
stderr=subprocess.STDOUT)
3117+
os.unlink(filename)
3118+
3119+
self.addCleanup(cleanup)
3120+
3121+
if support.verbose:
3122+
print("File:", filename)
3123+
print("stat with access:", stat1)
3124+
3125+
# First test - we shouldn't raise here, because we still have access to
3126+
# the directory and can extract enough information from its metadata.
3127+
stat2 = os.stat(filename)
3128+
3129+
if support.verbose:
3130+
print(" without access:", stat2)
3131+
3132+
# We cannot get st_dev/st_ino, so ensure those are 0 or else our test
3133+
# is not set up correctly
3134+
self.assertEqual(0, stat2.st_dev)
3135+
self.assertEqual(0, stat2.st_ino)
3136+
3137+
# st_mode and st_size should match (for a normal file, at least)
3138+
self.assertEqual(stat1.st_mode, stat2.st_mode)
3139+
self.assertEqual(stat1.st_size, stat2.st_size)
3140+
3141+
# st_ctime and st_mtime should be the same
3142+
self.assertEqual(stat1.st_ctime, stat2.st_ctime)
3143+
self.assertEqual(stat1.st_mtime, stat2.st_mtime)
3144+
3145+
# st_atime should be the same or later
3146+
self.assertGreaterEqual(stat1.st_atime, stat2.st_atime)
3147+
30883148

30893149
@os_helper.skip_unless_symlink
30903150
class NonLocalSymlinkTests(unittest.TestCase):
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
:func:`os.stat` calls were returning incorrect time values for files that
2+
could not be accessed directly.

Modules/posixmodule.c

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1886,8 +1886,9 @@ win32_xstat_slow_impl(const wchar_t *path, struct _Py_stat_struct *result,
18861886
HANDLE hFile;
18871887
BY_HANDLE_FILE_INFORMATION fileInfo;
18881888
FILE_BASIC_INFO basicInfo;
1889+
FILE_BASIC_INFO *pBasicInfo = NULL;
18891890
FILE_ID_INFO idInfo;
1890-
FILE_ID_INFO *pIdInfo = &idInfo;
1891+
FILE_ID_INFO *pIdInfo = NULL;
18911892
FILE_ATTRIBUTE_TAG_INFO tagInfo = { 0 };
18921893
DWORD fileType, error;
18931894
BOOL isUnhandledTag = FALSE;
@@ -2038,14 +2039,17 @@ win32_xstat_slow_impl(const wchar_t *path, struct _Py_stat_struct *result,
20382039
retval = -1;
20392040
goto cleanup;
20402041
}
2041-
}
20422042

2043-
if (!GetFileInformationByHandleEx(hFile, FileIdInfo, &idInfo, sizeof(idInfo))) {
2044-
/* Failed to get FileIdInfo, so do not pass it along */
2045-
pIdInfo = NULL;
2043+
/* Successfully got FileBasicInfo, so we'll pass it along */
2044+
pBasicInfo = &basicInfo;
2045+
2046+
if (GetFileInformationByHandleEx(hFile, FileIdInfo, &idInfo, sizeof(idInfo))) {
2047+
/* Successfully got FileIdInfo, so pass it along */
2048+
pIdInfo = &idInfo;
2049+
}
20462050
}
20472051

2048-
_Py_attribute_data_to_stat(&fileInfo, tagInfo.ReparseTag, &basicInfo, pIdInfo, result);
2052+
_Py_attribute_data_to_stat(&fileInfo, tagInfo.ReparseTag, pBasicInfo, pIdInfo, result);
20492053
update_st_mode_from_path(path, fileInfo.dwFileAttributes, result);
20502054

20512055
cleanup:

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad © 2024 Your Company Name. All rights reserved.





Check this box to remove all script contents from the fetched content.



Check this box to remove all images from the fetched content.


Check this box to remove all CSS styles from the fetched content.


Check this box to keep images inefficiently compressed and original size.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy