@@ -67,31 +67,25 @@ _PyFrame_GetBytecode(_PyInterpreterFrame *f)
6767#endif
6868}
6969
70- // Similar to PyUnstable_InterpreterFrame_GetLasti(), but return NULL if the
71- // frame is invalid or freed. Used by dump_frame() in Python/traceback.c. The
72- // function uses heuristics to detect freed memory, it's not 100% reliable .
73- static inline int _Py_NO_SANITIZE_THREAD
74- _PyFrame_SafeGetLasti ( struct _PyInterpreterFrame * f )
70+ // Safe version of _PyFrame_GetBytecode() for racy signal-handler contexts.
71+ // Takes an already-validated code object. Returns NULL if tlbc_index is
72+ // out of range (GIL-disabled only) .
73+ static inline _Py_CODEUNIT * _Py_NO_SANITIZE_THREAD
74+ _PyFrame_SafeGetBytecode ( _PyInterpreterFrame * f , PyCodeObject * code )
7575{
76- // Code based on _PyFrame_GetBytecode() but replace _PyFrame_GetCode()
77- // with _PyFrame_SafeGetCode().
78- PyCodeObject * co = _PyFrame_SafeGetCode (f );
79- if (co == NULL ) {
80- return -1 ;
81- }
82-
83- _Py_CODEUNIT * bytecode ;
8476#ifdef Py_GIL_DISABLED
85- _PyCodeArray * tlbc = _PyCode_GetTLBCArray (co );
86- assert (f -> tlbc_index >= 0 && f -> tlbc_index < tlbc -> size );
87- bytecode = (_Py_CODEUNIT * )tlbc -> entries [f -> tlbc_index ];
77+ _PyCodeArray * tlbc = _PyCode_GetTLBCArray (code );
78+ int idx = f -> tlbc_index ;
79+ if (idx < 0 || idx >= tlbc -> size ) {
80+ return NULL ;
81+ }
82+ return (_Py_CODEUNIT * )tlbc -> entries [idx ];
8883#else
89- bytecode = _PyCode_CODE (co );
84+ return _PyCode_CODE (code );
9085#endif
91-
92- return (int )(f -> instr_ptr - bytecode ) * sizeof (_Py_CODEUNIT );
9386}
9487
88+
9589static inline PyFunctionObject * _PyFrame_GetFunction (_PyInterpreterFrame * f ) {
9690 PyObject * func = PyStackRef_AsPyObjectBorrow (f -> f_funcobj );
9791 assert (PyFunction_Check (func ));
@@ -262,9 +256,18 @@ _PyFrame_IsIncomplete(_PyInterpreterFrame *frame)
262256 if (frame -> owner >= FRAME_OWNED_BY_INTERPRETER ) {
263257 return true;
264258 }
265- return frame -> owner != FRAME_OWNED_BY_GENERATOR &&
266- frame -> instr_ptr < _PyFrame_GetBytecode (frame ) +
267- _PyFrame_GetCode (frame )-> _co_firsttraceable ;
259+ if (frame -> owner == FRAME_OWNED_BY_GENERATOR ) {
260+ return false;
261+ }
262+ PyCodeObject * code = _PyFrame_SafeGetCode (frame );
263+ if (code == NULL ) {
264+ return true;
265+ }
266+ _Py_CODEUNIT * bytecode = _PyFrame_SafeGetBytecode (frame , code );
267+ if (bytecode == NULL ) {
268+ return true;
269+ }
270+ return frame -> instr_ptr < bytecode + code -> _co_firsttraceable ;
268271}
269272
270273static inline _PyInterpreterFrame *
0 commit comments