8000 [3.12] gh-110052: Fix faulthandler for freed tstate (#110069) (#110071) · python/cpython@d0641ab · GitHub
[go: up one dir, main page]

Skip to content

Commit d0641ab

Browse files
authored
[3.12] gh-110052: Fix faulthandler for freed tstate (#110069) (#110071)
gh-110052: Fix faulthandler for freed tstate (#110069) faulthandler now detected freed interp and freed tstate, and no longer dereference them. (cherry picked from commit 2e37a38)
1 parent a207491 commit d0641ab

File tree

2 files changed

+38
-12
lines changed

2 files changed

+38
-12
lines changed

Modules/faulthandler.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,6 @@ faulthandler_dump_traceback(int fd, int all_threads,
176176
PyInterpreterState *interp)
177177
{
178178
static volatile int reentrant = 0;
179-
PyThreadState *tstate;
180179

181180
if (reentrant)
182181
return;
@@ -191,7 +190,7 @@ faulthandler_dump_traceback(int fd, int all_threads,
191190
fault if the thread released the GIL, and so this function cannot be
192191
used. Read the thread specific storage (TSS) instead: call
193192
PyGILState_GetThisThreadState(). */
194-
tstate = PyGILState_GetThisThreadState();
193+
PyThreadState *tstate = PyGILState_GetThisThreadState();
195194

196195
if (all_threads) {
197196
(void)_Py_DumpTracebackThreads(fd, NULL, tstate);

Python/traceback.c

Lines changed: 37 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1218,23 +1218,45 @@ dump_frame(int fd, _PyInterpreterFrame *frame)
12181218
PUTS(fd, "\n");
12191219
}
12201220

1221+
static int
1222+
tstate_is_freed(PyThreadState *tstate)
1223+
{
1224+
if (_PyMem_IsPtrFreed(tstate)) {
1225+
return 1;
1226+
}
1227+
if (_PyMem_IsPtrFreed(tstate->interp)) {
1228+
return 1;
1229+
}
1230+
return 0;
1231+
}
1232+
1233+
1234+
static int
1235+
interp_is_freed(PyInterpreterState *interp)
1236+
{
1237+
return _PyMem_IsPtrFreed(interp);
1238+
}
1239+
1240+
12211241
static void
12221242
dump_traceback(int fd, PyThreadState *tstate, int write_header)
12231243
{
1224-
_PyInterpreterFrame *frame;
1225-
unsigned int depth;
1226-
12271244
if (write_header) {
12281245
PUTS(fd, "Stack (most recent call first):\n");
12291246
}
12301247

1231-
frame = tstate->cframe->current_frame;
1248+
if (tstate_is_freed(tstate)) {
1249+
PUTS(fd, " <tstate is freed>\n");
1250+
return;
1251+
}
1252+
1253+
_PyInterpreterFrame *frame = tstate->cframe->current_frame;
12321254
if (frame == NULL) {
12331255
PUTS(fd, " <no Python frame>\n");
12341256
return;
12351257
}
12361258

1237-
depth = 0;
1259+
unsigned int depth = 0;
12381260
while (1) {
12391261
if (MAX_FRAME_DEPTH <= depth) {
12401262
PUTS(fd, " ...\n");
@@ -1298,9 +1320,6 @@ const char*
12981320
_Py_DumpTracebackThreads(int fd, PyInterpreterState *interp,
12991321
PyThreadState *current_tstate)
13001322
{
1301-
PyThreadState *tstate;
1302-
unsigned int nthreads;
1303-
13041323
if (current_tstate == NULL) {
13051324
/* _Py_DumpTracebackThreads() is called from signal handlers by
13061325
faulthandler.
@@ -1316,6 +1335,10 @@ _Py_DumpTracebackThreads(int fd, PyInterpreterState *interp,
13161335
current_tstate = PyGILState_GetThisThreadState();
13171336
}
13181337

1338+
if (current_tstate != NULL && tstate_is_freed(current_tstate)) {
1339+
return "tstate is freed";
1340+
}
1341+
13191342
if (interp == NULL) {
13201343
if (current_tstate == NULL) {
13211344
interp = _PyGILState_GetInterpreterStateUnsafe();
@@ -1330,14 +1353,18 @@ _Py_DumpTracebackThreads(int fd, PyInterpreterState *interp,
13301353
}
13311354
assert(interp != NULL);
13321355

1356+
if (interp_is_freed(interp)) {
1357+
return "interp is freed";
1358+
}
1359+
13331360
/* Get the current interpreter from the current thread */
1334-
tstate = PyInterpreterState_ThreadHead(interp);
1361+
PyThreadState *tstate = PyInterpreterState_ThreadHead(interp);
13351362
if (tstate == NULL)
13361363
return "unable to get the thread head state";
13371364

13381365
/* Dump the traceback of each thread */
13391366
tstate = PyInterpreterState_ThreadHead(interp);
1340-
nthreads = 0;
1367+
unsigned int nthreads = 0;
13411368
_Py_BEGIN_SUPPRESS_IPH
13421369
do
13431370
{

0 commit comments

Comments
 (0)
0