Skip to content

Commit 72dd471

Browse files
authored
gh-120754: _io Ensure stat cache is cleared on fd change (#125166)
Performed an audit of `fileio.c` and `_pyio` and made sure anytime the fd changes the stat result, if set, is also cleared/changed. There's one case where it's not cleared, if code would clear it in __init__, keep the memory allocated and just do another fstat with the existing memory.
1 parent c84a136 commit 72dd471

File tree

2 files changed

+9
-5
lines changed

2 files changed

+9
-5
lines changed

Lib/_pyio.py

+3
Original file line numberDiff line numberDiff line change
@@ -1480,6 +1480,7 @@ def __init__(self, file, mode='r', closefd=True, opener=None):
14801480
"""
14811481
if self._fd >= 0:
14821482
# Have to close the existing file first.
1483+
self._stat_atopen = None
14831484
try:
14841485
if self._closefd:
14851486
os.close(self._fd)
@@ -1583,6 +1584,7 @@ def __init__(self, file, mode='r', closefd=True, opener=None):
15831584
if e.errno != errno.ESPIPE:
15841585
raise
15851586
except:
1587+
self._stat_atopen = None
15861588
if owned_fd is not None:
15871589
os.close(owned_fd)
15881590
raise
@@ -1756,6 +1758,7 @@ def close(self):
17561758
called more than once without error.
17571759
"""
17581760
if not self.closed:
1761+
self._stat_atopen = None
17591762
try:
17601763
if self._closefd:
17611764
os.close(self._fd)

Modules/_io/fileio.c

+6-5
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,8 @@ internal_close(fileio *self)
131131
_Py_END_SUPPRESS_IPH
132132
Py_END_ALLOW_THREADS
133133
}
134+
PyMem_Free(self->stat_atopen);
135+
self->stat_atopen = NULL;
134136
if (err < 0) {
135137
errno = save_errno;
136138
PyErr_SetFromErrno(PyExc_OSError);
@@ -268,8 +270,9 @@ _io_FileIO___init___impl(fileio *self, PyObject *nameobj, const char *mode,
268270
if (self->fd >= 0) {
269271
if (self->closefd) {
270272
/* Have to close the existing file first. */
271-
if (internal_close(self) < 0)
273+
if (internal_close(self) < 0) {
272274
return -1;
275+
}
273276
}
274277
else
275278
self->fd = -1;
@@ -523,10 +526,8 @@ _io_FileIO___init___impl(fileio *self, PyObject *nameobj, const char *mode,
523526
internal_close(self);
524527
_PyErr_ChainExceptions1(exc);
525528
}
526-
if (self->stat_atopen != NULL) {
527-
PyMem_Free(self->stat_atopen);
528-
self->stat_atopen = NULL;
529-
}
529+
PyMem_Free(self->stat_atopen);
530+
self->stat_atopen = NULL;
530531

531532
done:
532533
#ifdef MS_WINDOWS

0 commit comments

Comments
 (0)