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.
This commit is contained in:
Victor Stinner 2025-11-04 11:48:28 +01:00 committed by GitHub
parent 08115d241a
commit a84181c31b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 128 additions and 33 deletions

View file

@ -1005,8 +1005,8 @@ PyCode_NewEmpty(const char *filename, const char *funcname, int firstlineno)
* source location tracking (co_lines/co_positions)
******************/
int
_PyCode_Addr2LineNoTstate(PyCodeObject *co, int addrq)
static int
_PyCode_Addr2Line(PyCodeObject *co, int addrq)
{
if (addrq < 0) {
return co->co_firstlineno;
@ -1020,12 +1020,29 @@ _PyCode_Addr2LineNoTstate(PyCodeObject *co, int addrq)
return _PyCode_CheckLineNumber(addrq, &bounds);
}
int
_PyCode_SafeAddr2Line(PyCodeObject *co, int addrq)
{
if (addrq < 0) {
return co->co_firstlineno;
}
if (co->_co_monitoring && co->_co_monitoring->lines) {
return _Py_Instrumentation_GetLine(co, addrq/sizeof(_Py_CODEUNIT));
}
if (!(addrq >= 0 && addrq < _PyCode_NBYTES(co))) {
return -1;
}
PyCodeAddressRange bounds;
_PyCode_InitAddressRange(co, &bounds);
return _PyCode_CheckLineNumber(addrq, &bounds);
}
int
PyCode_Addr2Line(PyCodeObject *co, int addrq)
{
int lineno;
Py_BEGIN_CRITICAL_SECTION(co);
lineno = _PyCode_Addr2LineNoTstate(co, addrq);
lineno = _PyCode_Addr2Line(co, addrq);
Py_END_CRITICAL_SECTION();
return lineno;
}