mirror of
https://github.com/python/cpython.git
synced 2025-12-08 06:10:17 +00:00
gh-140815: Fix faulthandler for invalid/freed frame (#140921)
faulthandler now detects if a frame or a code object is invalid or
freed.
Add helper functions:
* _PyCode_SafeAddr2Line()
* _PyFrame_SafeGetCode()
* _PyFrame_SafeGetLasti()
_PyMem_IsPtrFreed() now detects pointers in [-0xff, 0xff] range
as freed.
(cherry picked from commit a84181c31b)
This commit is contained in:
parent
7ac9048ce9
commit
43882c7c4e
6 changed files with 108 additions and 26 deletions
|
|
@ -894,14 +894,24 @@ _Py_DumpASCII(int fd, PyObject *text)
|
|||
|
||||
/* Write a frame into the file fd: "File "xxx", line xxx in xxx".
|
||||
|
||||
This function is signal safe. */
|
||||
This function is signal safe.
|
||||
|
||||
static void
|
||||
Return 0 on success. Return -1 if the frame is invalid. */
|
||||
|
||||
static int
|
||||
dump_frame(int fd, _PyInterpreterFrame *frame)
|
||||
{
|
||||
assert(frame->owner != FRAME_OWNED_BY_CSTACK);
|
||||
if (frame->owner == FRAME_OWNED_BY_CSTACK) {
|
||||
/* Ignore trampoline frame */
|
||||
return 0;
|
||||
}
|
||||
|
||||
PyCodeObject *code =_PyFrame_GetCode(frame);
|
||||
PyCodeObject *code = _PyFrame_SafeGetCode(frame);
|
||||
if (code == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
int res = 0;
|
||||
PUTS(fd, " File ");
|
||||
if (code->co_filename != NULL
|
||||
&& PyUnicode_Check(code->co_filename))
|
||||
|
|
@ -909,29 +919,36 @@ dump_frame(int fd, _PyInterpreterFrame *frame)
|
|||
PUTS(fd, "\"");
|
||||
_Py_DumpASCII(fd, code->co_filename);
|
||||
PUTS(fd, "\"");
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
PUTS(fd, "???");
|
||||
res = -1;
|
||||
}
|
||||
|
||||
int lineno = PyUnstable_InterpreterFrame_GetLine(frame);
|
||||
PUTS(fd, ", line ");
|
||||
int lasti = _PyFrame_SafeGetLasti(frame);
|
||||
int lineno = -1;
|
||||
if (lasti >= 0) {
|
||||
lineno = _PyCode_SafeAddr2Line(code, lasti);
|
||||
}
|
||||
if (lineno >= 0) {
|
||||
_Py_DumpDecimal(fd, (size_t)lineno);
|
||||
}
|
||||
else {
|
||||
PUTS(fd, "???");
|
||||
res = -1;
|
||||
}
|
||||
PUTS(fd, " in ");
|
||||
|
||||
if (code->co_name != NULL
|
||||
&& PyUnicode_Check(code->co_name)) {
|
||||
PUTS(fd, " in ");
|
||||
if (code->co_name != NULL && PyUnicode_Check(code->co_name)) {
|
||||
_Py_DumpASCII(fd, code->co_name);
|
||||
}
|
||||
else {
|
||||
PUTS(fd, "???");
|
||||
res = -1;
|
||||
}
|
||||
|
||||
PUTS(fd, "\n");
|
||||
return res;
|
||||
}
|
||||
|
||||
static int
|
||||
|
|
@ -974,17 +991,6 @@ dump_traceback(int fd, PyThreadState *tstate, int write_header)
|
|||
|
||||
unsigned int depth = 0;
|
||||
while (1) {
|
||||
if (frame->owner == FRAME_OWNED_BY_CSTACK) {
|
||||
/* Trampoline frame */
|
||||
frame = frame->previous;
|
||||
if (frame == NULL) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* Can't have more than one shim frame in a row */
|
||||
assert(frame->owner != FRAME_OWNED_BY_CSTACK);
|
||||
}
|
||||
|
||||
if (MAX_FRAME_DEPTH <= depth) {
|
||||
if (MAX_FRAME_DEPTH < depth) {
|
||||
PUTS(fd, "plus ");
|
||||
|
|
@ -994,7 +1000,15 @@ dump_traceback(int fd, PyThreadState *tstate, int write_header)
|
|||
break;
|
||||
}
|
||||
|
||||
dump_frame(fd, frame);
|
||||
if (_PyMem_IsPtrFreed(frame)) {
|
||||
PUTS(fd, " <freed frame>\n");
|
||||
break;
|
||||
}
|
||||
if (dump_frame(fd, frame) < 0) {
|
||||
PUTS(fd, " <invalid frame>\n");
|
||||
break;
|
||||
}
|
||||
|
||||
frame = frame->previous;
|
||||
if (frame == NULL) {
|
||||
break;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue