gh-128421: add critical section around traceback.tb_next (#131322)

This commit is contained in:
Kumar Aditya 2025-03-20 12:03:54 +05:30 committed by GitHub
parent b12af0a48f
commit 39b37b0110
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 82 additions and 14 deletions

View file

@ -99,10 +99,16 @@ tb_dir(PyObject *Py_UNUSED(self), PyObject *Py_UNUSED(ignored))
"tb_lasti", "tb_lineno");
}
/*[clinic input]
@critical_section
@getter
traceback.tb_next
[clinic start generated code]*/
static PyObject *
tb_next_get(PyObject *op, void *Py_UNUSED(_))
traceback_tb_next_get_impl(PyTracebackObject *self)
/*[clinic end generated code: output=963634df7d5fc837 input=8f6345f2b73cb965]*/
{
PyTracebackObject *self = _PyTracebackObject_CAST(op);
PyObject* ret = (PyObject*)self->tb_next;
if (!ret) {
ret = Py_None;
@ -133,37 +139,48 @@ tb_lineno_get(PyObject *op, void *Py_UNUSED(_))
return PyLong_FromLong(lineno);
}
/*[clinic input]
@critical_section
@setter
traceback.tb_next
[clinic start generated code]*/
static int
tb_next_set(PyObject *op, PyObject *new_next, void *Py_UNUSED(_))
traceback_tb_next_set_impl(PyTracebackObject *self, PyObject *value)
/*[clinic end generated code: output=d4868cbc48f2adac input=ce66367f85e3c443]*/
{
if (!new_next) {
if (!value) {
PyErr_Format(PyExc_TypeError, "can't delete tb_next attribute");
return -1;
}
/* We accept None or a traceback object, and map None -> NULL (inverse of
tb_next_get) */
if (new_next == Py_None) {
new_next = NULL;
} else if (!PyTraceBack_Check(new_next)) {
if (value == Py_None) {
value = NULL;
} else if (!PyTraceBack_Check(value)) {
PyErr_Format(PyExc_TypeError,
"expected traceback object, got '%s'",
Py_TYPE(new_next)->tp_name);
Py_TYPE(value)->tp_name);
return -1;
}
/* Check for loops */
PyTracebackObject *self = _PyTracebackObject_CAST(op);
PyTracebackObject *cursor = (PyTracebackObject *)new_next;
PyTracebackObject *cursor = (PyTracebackObject *)value;
Py_XINCREF(cursor);
while (cursor) {
if (cursor == self) {
PyErr_Format(PyExc_ValueError, "traceback loop detected");
Py_DECREF(cursor);
return -1;
}
cursor = cursor->tb_next;
Py_BEGIN_CRITICAL_SECTION(cursor);
Py_XINCREF(cursor->tb_next);
Py_SETREF(cursor, cursor->tb_next);
Py_END_CRITICAL_SECTION();
}
Py_XSETREF(self->tb_next, (PyTracebackObject *)Py_XNewRef(new_next));
Py_XSETREF(self->tb_next, (PyTracebackObject *)Py_XNewRef(value));
return 0;
}
@ -181,7 +198,7 @@ static PyMemberDef tb_memberlist[] = {
};
static PyGetSetDef tb_getsetters[] = {
{"tb_next", tb_next_get, tb_next_set, NULL, NULL},
TRACEBACK_TB_NEXT_GETSETDEF
{"tb_lineno", tb_lineno_get, NULL, NULL, NULL},
{NULL} /* Sentinel */
};