mirror of
https://github.com/python/cpython.git
synced 2025-08-03 16:39:00 +00:00
gh-109613: _pystat_fromstructstat() checks for exceptions (#109618)
Fix os.stat() and os.DirEntry.stat(): check for exceptions. Previously, on Python built in debug mode, these functions could trigger a fatal Python error (and abort the process) when a function succeeded with an exception set. _pystat_fromstructstat() now exits immediately if an exception is raised, rather only checking for exceptions at the end. It fix following fatal error in fill_time(): Fatal Python error: _Py_CheckSlotResult: Slot * of type int succeeded with an exception set
This commit is contained in:
parent
115c49ad5a
commit
d4cea794a7
2 changed files with 76 additions and 49 deletions
|
@ -2396,21 +2396,26 @@ _posix_free(void *module)
|
|||
_posix_clear((PyObject *)module);
|
||||
}
|
||||
|
||||
static void
|
||||
static int
|
||||
fill_time(PyObject *module, PyObject *v, int s_index, int f_index, int ns_index, time_t sec, unsigned long nsec)
|
||||
{
|
||||
PyObject *s = _PyLong_FromTime_t(sec);
|
||||
PyObject *ns_fractional = PyLong_FromUnsignedLong(nsec);
|
||||
assert(!PyErr_Occurred());
|
||||
|
||||
int res = -1;
|
||||
PyObject *s_in_ns = NULL;
|
||||
PyObject *ns_total = NULL;
|
||||
PyObject *float_s = NULL;
|
||||
|
||||
if (!(s && ns_fractional))
|
||||
PyObject *s = _PyLong_FromTime_t(sec);
|
||||
PyObject *ns_fractional = PyLong_FromUnsignedLong(nsec);
|
||||
if (!(s && ns_fractional)) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
s_in_ns = PyNumber_Multiply(s, get_posix_state(module)->billion);
|
||||
if (!s_in_ns)
|
||||
if (!s_in_ns) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
ns_total = PyNumber_Add(s_in_ns, ns_fractional);
|
||||
if (!ns_total)
|
||||
|
@ -2433,12 +2438,17 @@ fill_time(PyObject *module, PyObject *v, int s_index, int f_index, int ns_index,
|
|||
PyStructSequence_SET_ITEM(v, ns_index, ns_total);
|
||||
ns_total = NULL;
|
||||
}
|
||||
|
||||
assert(!PyErr_Occurred());
|
||||
res = 0;
|
||||
|
||||
exit:
|
||||
Py_XDECREF(s);
|
||||
Py_XDECREF(ns_fractional);
|
||||
Py_XDECREF(s_in_ns);
|
||||
Py_XDECREF(ns_total);
|
||||
Py_XDECREF(float_s);
|
||||
return res;
|
||||
}
|
||||
|
||||
#ifdef MS_WINDOWS
|
||||
|
@ -2473,34 +2483,47 @@ _pystat_l128_from_l64_l64(uint64_t low, uint64_t high)
|
|||
static PyObject*
|
||||
_pystat_fromstructstat(PyObject *module, STRUCT_STAT *st)
|
||||
{
|
||||
unsigned long ansec, mnsec, cnsec;
|
||||
assert(!PyErr_Occurred());
|
||||
|
||||
PyObject *StatResultType = get_posix_state(module)->StatResultType;
|
||||
PyObject *v = PyStructSequence_New((PyTypeObject *)StatResultType);
|
||||
if (v == NULL)
|
||||
if (v == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long)st->st_mode));
|
||||
#define SET_ITEM(pos, expr) \
|
||||
do { \
|
||||
PyObject *obj = (expr); \
|
||||
if (obj == NULL) { \
|
||||
goto error; \
|
||||
} \
|
||||
PyStructSequence_SET_ITEM(v, (pos), obj); \
|
||||
} while (0)
|
||||
|
||||
SET_ITEM(0, PyLong_FromLong((long)st->st_mode));
|
||||
#ifdef MS_WINDOWS
|
||||
PyStructSequence_SET_ITEM(v, 1, _pystat_l128_from_l64_l64(st->st_ino, st->st_ino_high));
|
||||
PyStructSequence_SET_ITEM(v, 2, PyLong_FromUnsignedLongLong(st->st_dev));
|
||||
SET_ITEM(1, _pystat_l128_from_l64_l64(st->st_ino, st->st_ino_high));
|
||||
SET_ITEM(2, PyLong_FromUnsignedLongLong(st->st_dev));
|
||||
#else
|
||||
static_assert(sizeof(unsigned long long) >= sizeof(st->st_ino),
|
||||
"stat.st_ino is larger than unsigned long long");
|
||||
PyStructSequence_SET_ITEM(v, 1, PyLong_FromUnsignedLongLong(st->st_ino));
|
||||
PyStructSequence_SET_ITEM(v, 2, _PyLong_FromDev(st->st_dev));
|
||||
SET_ITEM(1, PyLong_FromUnsignedLongLong(st->st_ino));
|
||||
SET_ITEM(2, _PyLong_FromDev(st->st_dev));
|
||||
#endif
|
||||
PyStructSequence_SET_ITEM(v, 3, PyLong_FromLong((long)st->st_nlink));
|
||||
SET_ITEM(3, PyLong_FromLong((long)st->st_nlink));
|
||||
#if defined(MS_WINDOWS)
|
||||
PyStructSequence_SET_ITEM(v, 4, PyLong_FromLong(0));
|
||||
PyStructSequence_SET_ITEM(v, 5, PyLong_FromLong(0));
|
||||
SET_ITEM(4, PyLong_FromLong(0));
|
||||
SET_ITEM(5, PyLong_FromLong(0));
|
||||
#else
|
||||
PyStructSequence_SET_ITEM(v, 4, _PyLong_FromUid(st->st_uid));
|
||||
PyStructSequence_SET_ITEM(v, 5, _PyLong_FromGid(st->st_gid));
|
||||
SET_ITEM(4, _PyLong_FromUid(st->st_uid));
|
||||
SET_ITEM(5, _PyLong_FromGid(st->st_gid));
|
||||
#endif
|
||||
static_assert(sizeof(long long) >= sizeof(st->st_size),
|
||||
"stat.st_size is larger than long long");
|
||||
PyStructSequence_SET_ITEM(v, 6, PyLong_FromLongLong(st->st_size));
|
||||
SET_ITEM(6, PyLong_FromLongLong(st->st_size));
|
||||
|
||||
// Set st_atime, st_mtime and st_ctime
|
||||
unsigned long ansec, mnsec, cnsec;
|
||||
#if defined(HAVE_STAT_TV_NSEC)
|
||||
ansec = st->st_atim.tv_nsec;
|
||||
mnsec = st->st_mtim.tv_nsec;
|
||||
|
@ -2516,67 +2539,67 @@ _pystat_fromstructstat(PyObject *module, STRUCT_STAT *st)
|
|||
#else
|
||||
ansec = mnsec = cnsec = 0;
|
||||
#endif
|
||||
fill_time(module, v, 7, 10, 13, st->st_atime, ansec);
|
||||
fill_time(module, v, 8, 11, 14, st->st_mtime, mnsec);
|
||||
fill_time(module, v, 9, 12, 15, st->st_ctime, cnsec);
|
||||
if (fill_time(module, v, 7, 10, 13, st->st_atime, ansec) < 0) {
|
||||
goto error;
|
||||
}
|
||||
if (fill_time(module, v, 8, 11, 14, st->st_mtime, mnsec) < 0) {
|
||||
goto error;
|
||||
}
|
||||
if (fill_time(module, v, 9, 12, 15, st->st_ctime, cnsec) < 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
|
||||
PyStructSequence_SET_ITEM(v, ST_BLKSIZE_IDX,
|
||||
PyLong_FromLong((long)st->st_blksize));
|
||||
SET_ITEM(ST_BLKSIZE_IDX, PyLong_FromLong((long)st->st_blksize));
|
||||
#endif
|
||||
#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
|
||||
PyStructSequence_SET_ITEM(v, ST_BLOCKS_IDX,
|
||||
PyLong_FromLong((long)st->st_blocks));
|
||||
SET_ITEM(ST_BLOCKS_IDX, PyLong_FromLong((long)st->st_blocks));
|
||||
#endif
|
||||
#ifdef HAVE_STRUCT_STAT_ST_RDEV
|
||||
PyStructSequence_SET_ITEM(v, ST_RDEV_IDX,
|
||||
PyLong_FromLong((long)st->st_rdev));
|
||||
SET_ITEM(ST_RDEV_IDX, PyLong_FromLong((long)st->st_rdev));
|
||||
#endif
|
||||
#ifdef HAVE_STRUCT_STAT_ST_GEN
|
||||
PyStructSequence_SET_ITEM(v, ST_GEN_IDX,
|
||||
PyLong_FromLong((long)st->st_gen));
|
||||
SET_ITEM(ST_GEN_IDX, PyLong_FromLong((long)st->st_gen));
|
||||
#endif
|
||||
#if defined(HAVE_STRUCT_STAT_ST_BIRTHTIME)
|
||||
{
|
||||
PyObject *val;
|
||||
unsigned long bsec,bnsec;
|
||||
unsigned long bsec, bnsec;
|
||||
bsec = (long)st->st_birthtime;
|
||||
#ifdef HAVE_STAT_TV_NSEC2
|
||||
bnsec = st->st_birthtimespec.tv_nsec;
|
||||
#else
|
||||
bnsec = 0;
|
||||
#endif
|
||||
val = PyFloat_FromDouble(bsec + 1e-9*bnsec);
|
||||
PyStructSequence_SET_ITEM(v, ST_BIRTHTIME_IDX,
|
||||
val);
|
||||
SET_ITEM(ST_BIRTHTIME_IDX, PyFloat_FromDouble(bsec + bnsec * 1e-9));
|
||||
}
|
||||
#elif defined(MS_WINDOWS)
|
||||
fill_time(module, v, -1, ST_BIRTHTIME_IDX, ST_BIRTHTIME_NS_IDX,
|
||||
st->st_birthtime, st->st_birthtime_nsec);
|
||||
if (fill_time(module, v, -1, ST_BIRTHTIME_IDX, ST_BIRTHTIME_NS_IDX,
|
||||
st->st_birthtime, st->st_birthtime_nsec) < 0) {
|
||||
goto error;
|
||||
}
|
||||
#endif
|
||||
#ifdef HAVE_STRUCT_STAT_ST_FLAGS
|
||||
PyStructSequence_SET_ITEM(v, ST_FLAGS_IDX,
|
||||
PyLong_FromLong((long)st->st_flags));
|
||||
SET_ITEM(ST_FLAGS_IDX, PyLong_FromLong((long)st->st_flags));
|
||||
#endif
|
||||
#ifdef HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES
|
||||
PyStructSequence_SET_ITEM(v, ST_FILE_ATTRIBUTES_IDX,
|
||||
PyLong_FromUnsignedLong(st->st_file_attributes));
|
||||
SET_ITEM(ST_FILE_ATTRIBUTES_IDX,
|
||||
PyLong_FromUnsignedLong(st->st_file_attributes));
|
||||
#endif
|
||||
#ifdef HAVE_STRUCT_STAT_ST_FSTYPE
|
||||
PyStructSequence_SET_ITEM(v, ST_FSTYPE_IDX,
|
||||
PyUnicode_FromString(st->st_fstype));
|
||||
SET_ITEM(ST_FSTYPE_IDX, PyUnicode_FromString(st->st_fstype));
|
||||
#endif
|
||||
#ifdef HAVE_STRUCT_STAT_ST_REPARSE_TAG
|
||||
PyStructSequence_SET_ITEM(v, ST_REPARSE_TAG_IDX,
|
||||
PyLong_FromUnsignedLong(st->st_reparse_tag));
|
||||
SET_ITEM(ST_REPARSE_TAG_IDX, PyLong_FromUnsignedLong(st->st_reparse_tag));
|
||||
#endif
|
||||
|
||||
if (PyErr_Occurred()) {
|
||||
Py_DECREF(v);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
assert(!PyErr_Occurred());
|
||||
return v;
|
||||
|
||||
error:
|
||||
Py_DECREF(v);
|
||||
return NULL;
|
||||
|
||||
#undef SET_ITEM
|
||||
}
|
||||
|
||||
/* POSIX methods */
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue