Skip to content

gh-111178: fix UBSan failures in Python/traceback.c #128259

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Jan 27, 2025
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
fix UBSan failures for PyTracebackObject
  • Loading branch information
picnixz committed Dec 25, 2024
commit a410b26b7f7930f00d53902146b47d1d6ea8876e
39 changes: 24 additions & 15 deletions Python/traceback.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@
[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 *
Expand Down Expand Up @@ -91,35 +93,38 @@
}

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)

Check warning on line 105 in Python/traceback.c

View workflow job for this annotation

GitHub Actions / Ubuntu (free-threading) / build and test (ubuntu-24.04)

unused variable ‘self’ [-Wunused-variable]

Check warning on line 105 in Python/traceback.c

View workflow job for this annotation

GitHub Actions / Hypothesis tests on Ubuntu

unused variable ‘self’ [-Wunused-variable]

Check warning on line 105 in Python/traceback.c

View workflow job for this annotation

GitHub Actions / Ubuntu / build and test (ubuntu-24.04)

unused variable ‘self’ [-Wunused-variable]
PyObject* ret = (PyObject*)self->tb_next;

Check failure on line 106 in Python/traceback.c

View workflow job for this annotation

GitHub Actions / Ubuntu (free-threading) / build and test (ubuntu-24.04)

expected ‘,’ or ‘;’ before ‘PyObject’

Check failure on line 106 in Python/traceback.c

View workflow job for this annotation

GitHub Actions / Hypothesis tests on Ubuntu

expected ‘,’ or ‘;’ before ‘PyObject’

Check failure on line 106 in Python/traceback.c

View workflow job for this annotation

GitHub Actions / Ubuntu / build and test (ubuntu-24.04)

expected ‘,’ or ‘;’ before ‘PyObject’
if (!ret) {

Check failure on line 107 in Python/traceback.c

View workflow job for this annotation

GitHub Actions / Ubuntu (free-threading) / build and test (ubuntu-24.04)

‘ret’ undeclared (first use in this function)

Check failure on line 107 in Python/traceback.c

View workflow job for this annotation

GitHub Actions / Hypothesis tests on Ubuntu

‘ret’ undeclared (first use in this function)

Check failure on line 107 in Python/traceback.c

View workflow job for this annotation

GitHub Actions / Ubuntu / build and test (ubuntu-24.04)

‘ret’ undeclared (first use in this function)
ret = Py_None;
}
return Py_NewRef(ret);
}

Check warning on line 111 in Python/traceback.c

View workflow job for this annotation

GitHub Actions / Ubuntu (free-threading) / build and test (ubuntu-24.04)

control reaches end of non-void function [-Wreturn-type]

Check warning on line 111 in Python/traceback.c

View workflow job for this annotation

GitHub Actions / Hypothesis tests on Ubuntu

control reaches end of non-void function [-Wreturn-type]

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);

Check warning on line 127 in Python/traceback.c

View workflow job for this annotation

GitHub Actions / Ubuntu (free-threading) / build and test (ubuntu-24.04)

passing argument 1 of ‘tb_get_lineno’ from incompatible pointer type [-Wincompatible-pointer-types]

Check warning on line 127 in Python/traceback.c

View workflow job for this annotation

GitHub Actions / Hypothesis tests on Ubuntu

passing argument 1 of ‘tb_get_lineno’ from incompatible pointer type [-Wincompatible-pointer-types]
if (lineno < 0) {
Py_RETURN_NONE;
}
Expand All @@ -128,7 +133,7 @@
}

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");
Expand All @@ -147,6 +152,7 @@
}

/* Check for loops */
PyTracebackObject *self = _PyTracebackObject_CAST(op);
PyTracebackObject *cursor = (PyTracebackObject *)new_next;
while (cursor) {
if (cursor == self) {
Expand All @@ -163,7 +169,7 @@


static PyMethodDef tb_methods[] = {
{"__dir__", _PyCFunction_CAST(tb_dir), METH_NOARGS},
{"__dir__", tb_dir, METH_NOARGS, NULL},
{NULL, NULL, 0, NULL},
};

Expand All @@ -174,14 +180,15 @@
};

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);
Expand All @@ -191,16 +198,18 @@
}

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;
Expand All @@ -211,7 +220,7 @@
"traceback",
sizeof(PyTracebackObject),
0,
(destructor)tb_dealloc, /*tp_dealloc*/
tb_dealloc, /*tp_dealloc*/
0, /*tp_vectorcall_offset*/
0, /*tp_getattr*/
0, /*tp_setattr*/
Expand All @@ -228,8 +237,8 @@
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 */
Expand Down Expand Up @@ -663,7 +672,7 @@
code = PyFrame_GetCode(tb->tb_frame);
int tb_lineno = tb->tb_lineno;
if (tb_lineno == -1) {
tb_lineno = tb_get_lineno(tb);

Check warning on line 675 in Python/traceback.c

View workflow job for this annotation

GitHub Actions / Ubuntu (free-threading) / build and test (ubuntu-24.04)

passing argument 1 of ‘tb_get_lineno’ from incompatible pointer type [-Wincompatible-pointer-types]

Check warning on line 675 in Python/traceback.c

View workflow job for this annotation

GitHub Actions / Hypothesis tests on Ubuntu

passing argument 1 of ‘tb_get_lineno’ from incompatible pointer type [-Wincompatible-pointer-types]
}
if (last_file == NULL ||
code->co_filename != last_file ||
Expand Down
Loading