]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-111178: fix UBSan failures in `Python/traceback.c` (GH-128259)
authorBénédikt Tran <10796600+picnixz@users.noreply.github.com>
Mon, 27 Jan 2025 14:07:39 +0000 (15:07 +0100)
committerGitHub <noreply@github.com>
Mon, 27 Jan 2025 14:07:39 +0000 (15:07 +0100)
Python/traceback.c

index 62387f12392265d1b67f52a43664e7616e9fe02a..870ae5bcefe9eb5b36e7ec418d72c89e0e4cd85c 100644 (file)
@@ -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 *Py_UNUSED(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,18 +111,21 @@ 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);
+        lineno = tb_get_lineno(op);
         if (lineno < 0) {
             Py_RETURN_NONE;
         }
@@ -128,7 +134,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 +153,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 +170,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 +181,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},
+    {"tb_next", tb_next_get, tb_next_set, NULL, NULL},
+    {"tb_lineno", tb_lineno_get, 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 +199,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 +221,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 +238,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 */
@@ -663,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 ||