https://github.com/python/cpython/commit/39b37b0110d0faaa25d7cdaab008f856eec8173c commit: 39b37b0110d0faaa25d7cdaab008f856eec8173c branch: main author: Kumar Aditya <kumaradi...@python.org> committer: kumaraditya303 <kumaradi...@python.org> date: 2025-03-20T12:03:54+05:30 summary:
gh-128421: add critical section around `traceback.tb_next` (#131322) files: M Python/clinic/traceback.c.h M Python/traceback.c diff --git a/Python/clinic/traceback.c.h b/Python/clinic/traceback.c.h index 9607e773f4be88..5eb31a189467b3 100644 --- a/Python/clinic/traceback.c.h +++ b/Python/clinic/traceback.c.h @@ -6,6 +6,7 @@ preserve # include "pycore_gc.h" // PyGC_Head # include "pycore_runtime.h" // _Py_ID() #endif +#include "pycore_critical_section.h"// Py_BEGIN_CRITICAL_SECTION() #include "pycore_modsupport.h" // _PyArg_UnpackKeywords() PyDoc_STRVAR(tb_new__doc__, @@ -79,4 +80,54 @@ tb_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) exit: return return_value; } -/*[clinic end generated code: output=62ebc0196940f663 input=a9049054013a1b77]*/ + +#if !defined(traceback_tb_next_DOCSTR) +# define traceback_tb_next_DOCSTR NULL +#endif +#if defined(TRACEBACK_TB_NEXT_GETSETDEF) +# undef TRACEBACK_TB_NEXT_GETSETDEF +# define TRACEBACK_TB_NEXT_GETSETDEF {"tb_next", (getter)traceback_tb_next_get, (setter)traceback_tb_next_set, traceback_tb_next_DOCSTR}, +#else +# define TRACEBACK_TB_NEXT_GETSETDEF {"tb_next", (getter)traceback_tb_next_get, NULL, traceback_tb_next_DOCSTR}, +#endif + +static PyObject * +traceback_tb_next_get_impl(PyTracebackObject *self); + +static PyObject * +traceback_tb_next_get(PyObject *self, void *Py_UNUSED(context)) +{ + PyObject *return_value = NULL; + + Py_BEGIN_CRITICAL_SECTION(self); + return_value = traceback_tb_next_get_impl((PyTracebackObject *)self); + Py_END_CRITICAL_SECTION(); + + return return_value; +} + +#if !defined(traceback_tb_next_DOCSTR) +# define traceback_tb_next_DOCSTR NULL +#endif +#if defined(TRACEBACK_TB_NEXT_GETSETDEF) +# undef TRACEBACK_TB_NEXT_GETSETDEF +# define TRACEBACK_TB_NEXT_GETSETDEF {"tb_next", (getter)traceback_tb_next_get, (setter)traceback_tb_next_set, traceback_tb_next_DOCSTR}, +#else +# define TRACEBACK_TB_NEXT_GETSETDEF {"tb_next", NULL, (setter)traceback_tb_next_set, NULL}, +#endif + +static int +traceback_tb_next_set_impl(PyTracebackObject *self, PyObject *value); + +static int +traceback_tb_next_set(PyObject *self, PyObject *value, void *Py_UNUSED(context)) +{ + int return_value; + + Py_BEGIN_CRITICAL_SECTION(self); + return_value = traceback_tb_next_set_impl((PyTracebackObject *)self, value); + Py_END_CRITICAL_SECTION(); + + return return_value; +} +/*[clinic end generated code: output=ca43786e235e38f4 input=a9049054013a1b77]*/ diff --git a/Python/traceback.c b/Python/traceback.c index e53d87d52f9c33..07a7ca8e7d63e4 100644 --- a/Python/traceback.c +++ b/Python/traceback.c @@ -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 */ }; _______________________________________________ Python-checkins mailing list -- python-checkins@python.org To unsubscribe send an email to python-checkins-le...@python.org https://mail.python.org/mailman3/lists/python-checkins.python.org/ Member address: arch...@mail-archive.com