Skip to content

Commit 671d19b

Browse files
committed
ensure we get bytecode safely as well
1 parent 4448ac8 commit 671d19b

1 file changed

Lines changed: 25 additions & 22 deletions

File tree

Include/internal/pycore_interpframe.h

Lines changed: 25 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
9589
static 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

270273
static inline _PyInterpreterFrame *

0 commit comments

Comments
 (0)