summaryrefslogtreecommitdiffstats
path: root/Python/traceback.c
diff options
context:
space:
mode:
authorVictor Stinner <vstinner@python.org>2023-09-29 02:43:28 (GMT)
committerGitHub <noreply@github.com>2023-09-29 02:43:28 (GMT)
commit615d7fc34a2b584ba39980db6ed99c90a90a445c (patch)
treeb90f91d38e916635edb18bdc6d9d072934199f0b /Python/traceback.c
parentefe83ad2762e3ea8b396b44947033445c9b31d04 (diff)
downloadcpython-615d7fc34a2b584ba39980db6ed99c90a90a445c.zip
cpython-615d7fc34a2b584ba39980db6ed99c90a90a445c.tar.gz
cpython-615d7fc34a2b584ba39980db6ed99c90a90a445c.tar.bz2
[3.11] gh-110052: Fix faulthandler for freed tstate (#110069) (#110072)
gh-110052: Fix faulthandler for freed tstate (#110069) faulthandler now detected freed interp and freed tstate, and no longer dereference them. Backport to 3.11: add pycore_pymem.h include to traceback.c. (cherry picked from commit 2e37a38bcbfbe1357436e030538290e7d00b668d)
Diffstat (limited to 'Python/traceback.c')
-rw-r--r--Python/traceback.c48
1 files changed, 38 insertions, 10 deletions
diff --git a/Python/traceback.c b/Python/traceback.c
index 7010736..c4f5ec8 100644
--- a/Python/traceback.c
+++ b/Python/traceback.c
@@ -12,6 +12,7 @@
#include "pycore_parser.h" // _PyParser_ASTFromString
#include "pycore_pyarena.h" // _PyArena_Free()
#include "pycore_pyerrors.h" // _PyErr_Fetch()
+#include "pycore_pymem.h" // _PyMem_IsPtrFreed()
#include "pycore_pystate.h" // _PyThreadState_GET()
#include "pycore_traceback.h" // EXCEPTION_TB_HEADER
@@ -1234,23 +1235,45 @@ dump_frame(int fd, _PyInterpreterFrame *frame)
PUTS(fd, "\n");
}
+static int
+tstate_is_freed(PyThreadState *tstate)
+{
+ if (_PyMem_IsPtrFreed(tstate)) {
+ return 1;
+ }
+ if (_PyMem_IsPtrFreed(tstate->interp)) {
+ return 1;
+ }
+ return 0;
+}
+
+
+static int
+interp_is_freed(PyInterpreterState *interp)
+{
+ return _PyMem_IsPtrFreed(interp);
+}
+
+
static void
dump_traceback(int fd, PyThreadState *tstate, int write_header)
{
- _PyInterpreterFrame *frame;
- unsigned int depth;
-
if (write_header) {
PUTS(fd, "Stack (most recent call first):\n");
}
- frame = tstate->cframe->current_frame;
+ if (tstate_is_freed(tstate)) {
+ PUTS(fd, " <tstate is freed>\n");
+ return;
+ }
+
+ _PyInterpreterFrame *frame = tstate->cframe->current_frame;
if (frame == NULL) {
PUTS(fd, " <no Python frame>\n");
return;
}
- depth = 0;
+ unsigned int depth = 0;
while (1) {
if (MAX_FRAME_DEPTH <= depth) {
PUTS(fd, " ...\n");
@@ -1305,9 +1328,6 @@ const char*
_Py_DumpTracebackThreads(int fd, PyInterpreterState *interp,
PyThreadState *current_tstate)
{
- PyThreadState *tstate;
- unsigned int nthreads;
-
if (current_tstate == NULL) {
/* _Py_DumpTracebackThreads() is called from signal handlers by
faulthandler.
@@ -1323,6 +1343,10 @@ _Py_DumpTracebackThreads(int fd, PyInterpreterState *interp,
current_tstate = PyGILState_GetThisThreadState();
}
+ if (current_tstate != NULL && tstate_is_freed(current_tstate)) {
+ return "tstate is freed";
+ }
+
if (interp == NULL) {
if (current_tstate == NULL) {
interp = _PyGILState_GetInterpreterStateUnsafe();
@@ -1337,14 +1361,18 @@ _Py_DumpTracebackThreads(int fd, PyInterpreterState *interp,
}
assert(interp != NULL);
+ if (interp_is_freed(interp)) {
+ return "interp is freed";
+ }
+
/* Get the current interpreter from the current thread */
- tstate = PyInterpreterState_ThreadHead(interp);
+ PyThreadState *tstate = PyInterpreterState_ThreadHead(interp);
if (tstate == NULL)
return "unable to get the thread head state";
/* Dump the traceback of each thread */
tstate = PyInterpreterState_ThreadHead(interp);
- nthreads = 0;
+ unsigned int nthreads = 0;
_Py_BEGIN_SUPPRESS_IPH
do
{