From a410b26b7f7930f00d53902146b47d1d6ea8876e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Wed, 25 Dec 2024 13:15:17 +0100 Subject: [PATCH 1/3] fix UBSan failures for `PyTracebackObject` --- Python/traceback.c | 39 ++++++++++++++++++++++++--------------- 1 file changed, 24 insertions(+), 15 deletions(-) diff --git a/Python/traceback.c b/Python/traceback.c index e819909b6045c3..e0c89bda86c6b3 100644 --- a/Python/traceback.c +++ b/Python/traceback.c @@ -38,6 +38,8 @@ class traceback "PyTracebackObject *" "&PyTraceback_Type" [clinic start generated code]*/ /*[clinic end generated code: output=da39a3ee5e6b4b0d input=cf96294b2bebc811]*/ +#define _PyTracebackObject_CAST(op) ((PyTracebackObject *)(op)) + #include "clinic/traceback.c.h" static PyObject * @@ -91,15 +93,16 @@ tb_new_impl(PyTypeObject *type, PyObject *tb_next, PyFrameObject *tb_frame, } static PyObject * -tb_dir(PyTracebackObject *self, PyObject *Py_UNUSED(ignored)) +tb_dir(PyObject *self, PyObject *Py_UNUSED(ignored)) { return Py_BuildValue("[ssss]", "tb_frame", "tb_next", "tb_lasti", "tb_lineno"); } static PyObject * -tb_next_get(PyTracebackObject *self, void *Py_UNUSED(_)) +tb_next_get(PyObject *op, void *Py_UNUSED(_)) { + PyTracebackObject *self = _PyTracebackObject_CAST(op) PyObject* ret = (PyObject*)self->tb_next; if (!ret) { ret = Py_None; @@ -108,15 +111,17 @@ tb_next_get(PyTracebackObject *self, void *Py_UNUSED(_)) } static int -tb_get_lineno(PyTracebackObject* tb) { +tb_get_lineno(PyObject *op) { + PyTracebackObject *tb = _PyTracebackObject_CAST(op); _PyInterpreterFrame* frame = tb->tb_frame->f_frame; assert(frame != NULL); return PyCode_Addr2Line(_PyFrame_GetCode(frame), tb->tb_lasti); } static PyObject * -tb_lineno_get(PyTracebackObject *self, void *Py_UNUSED(_)) +tb_lineno_get(PyObject *op, void *Py_UNUSED(_)) { + PyTracebackObject *self = _PyTracebackObject_CAST(op); int lineno = self->tb_lineno; if (lineno == -1) { lineno = tb_get_lineno(self); @@ -128,7 +133,7 @@ tb_lineno_get(PyTracebackObject *self, void *Py_UNUSED(_)) } static int -tb_next_set(PyTracebackObject *self, PyObject *new_next, void *Py_UNUSED(_)) +tb_next_set(PyObject *op, PyObject *new_next, void *Py_UNUSED(_)) { if (!new_next) { PyErr_Format(PyExc_TypeError, "can't delete tb_next attribute"); @@ -147,6 +152,7 @@ tb_next_set(PyTracebackObject *self, PyObject *new_next, void *Py_UNUSED(_)) } /* Check for loops */ + PyTracebackObject *self = _PyTracebackObject_CAST(op); PyTracebackObject *cursor = (PyTracebackObject *)new_next; while (cursor) { if (cursor == self) { @@ -163,7 +169,7 @@ tb_next_set(PyTracebackObject *self, PyObject *new_next, void *Py_UNUSED(_)) static PyMethodDef tb_methods[] = { - {"__dir__", _PyCFunction_CAST(tb_dir), METH_NOARGS}, + {"__dir__", tb_dir, METH_NOARGS, NULL}, {NULL, NULL, 0, NULL}, }; @@ -174,14 +180,15 @@ static PyMemberDef tb_memberlist[] = { }; static PyGetSetDef tb_getsetters[] = { - {"tb_next", (getter)tb_next_get, (setter)tb_next_set, NULL, NULL}, - {"tb_lineno", (getter)tb_lineno_get, NULL, NULL, NULL}, - {NULL} /* Sentinel */ + {"tb_next", tb_next_get, tb_next_set, NULL, NULL}, + {"tb_lineno", tb_lineno_get, NULL, NULL, NULL}, + {NULL, NULL, NULL, NULL, NULL} /* Sentinel */ }; static void -tb_dealloc(PyTracebackObject *tb) +tb_dealloc(PyObject *op) { + PyTracebackObject *tb = _PyTracebackObject_CAST(op); PyObject_GC_UnTrack(tb); Py_TRASHCAN_BEGIN(tb, tb_dealloc) Py_XDECREF(tb->tb_next); @@ -191,16 +198,18 @@ tb_dealloc(PyTracebackObject *tb) } static int -tb_traverse(PyTracebackObject *tb, visitproc visit, void *arg) +tb_traverse(PyObject *op, visitproc visit, void *arg) { + PyTracebackObject *tb = _PyTracebackObject_CAST(op); Py_VISIT(tb->tb_next); Py_VISIT(tb->tb_frame); return 0; } static int -tb_clear(PyTracebackObject *tb) +tb_clear(PyObject *op) { + PyTracebackObject *tb = _PyTracebackObject_CAST(op); Py_CLEAR(tb->tb_next); Py_CLEAR(tb->tb_frame); return 0; @@ -211,7 +220,7 @@ PyTypeObject PyTraceBack_Type = { "traceback", sizeof(PyTracebackObject), 0, - (destructor)tb_dealloc, /*tp_dealloc*/ + tb_dealloc, /*tp_dealloc*/ 0, /*tp_vectorcall_offset*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ @@ -228,8 +237,8 @@ PyTypeObject PyTraceBack_Type = { 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */ tb_new__doc__, /* tp_doc */ - (traverseproc)tb_traverse, /* tp_traverse */ - (inquiry)tb_clear, /* tp_clear */ + tb_traverse, /* tp_traverse */ + tb_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ From 3cbe2c0d497a47c5cddef2947b5a3ecee41ced41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Wed, 25 Dec 2024 13:18:14 +0100 Subject: [PATCH 2/3] cosmetic upgrades --- Python/traceback.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Python/traceback.c b/Python/traceback.c index e0c89bda86c6b3..47e0ff42aa3f2c 100644 --- a/Python/traceback.c +++ b/Python/traceback.c @@ -93,7 +93,7 @@ tb_new_impl(PyTypeObject *type, PyObject *tb_next, PyFrameObject *tb_frame, } static PyObject * -tb_dir(PyObject *self, PyObject *Py_UNUSED(ignored)) +tb_dir(PyObject *Py_UNUSED(self), PyObject *Py_UNUSED(ignored)) { return Py_BuildValue("[ssss]", "tb_frame", "tb_next", "tb_lasti", "tb_lineno"); @@ -111,7 +111,8 @@ tb_next_get(PyObject *op, void *Py_UNUSED(_)) } static int -tb_get_lineno(PyObject *op) { +tb_get_lineno(PyObject *op) +{ PyTracebackObject *tb = _PyTracebackObject_CAST(op); _PyInterpreterFrame* frame = tb->tb_frame->f_frame; assert(frame != NULL); From ba62e8fbd9a50d06b450301f106ad410aac85e9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Wed, 25 Dec 2024 13:23:33 +0100 Subject: [PATCH 3/3] fix compilation --- Python/traceback.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Python/traceback.c b/Python/traceback.c index 47e0ff42aa3f2c..ac049732485117 100644 --- a/Python/traceback.c +++ b/Python/traceback.c @@ -102,7 +102,7 @@ tb_dir(PyObject *Py_UNUSED(self), PyObject *Py_UNUSED(ignored)) static PyObject * tb_next_get(PyObject *op, void *Py_UNUSED(_)) { - PyTracebackObject *self = _PyTracebackObject_CAST(op) + PyTracebackObject *self = _PyTracebackObject_CAST(op); PyObject* ret = (PyObject*)self->tb_next; if (!ret) { ret = Py_None; @@ -125,7 +125,7 @@ tb_lineno_get(PyObject *op, void *Py_UNUSED(_)) PyTracebackObject *self = _PyTracebackObject_CAST(op); int lineno = self->tb_lineno; if (lineno == -1) { - lineno = tb_get_lineno(self); + lineno = tb_get_lineno(op); if (lineno < 0) { Py_RETURN_NONE; } @@ -673,7 +673,7 @@ tb_printinternal(PyTracebackObject *tb, PyObject *f, long limit) code = PyFrame_GetCode(tb->tb_frame); int tb_lineno = tb->tb_lineno; if (tb_lineno == -1) { - tb_lineno = tb_get_lineno(tb); + tb_lineno = tb_get_lineno((PyObject *)tb); } if (last_file == NULL || code->co_filename != last_file ||