Skip to content

Commit ced296d

Browse files
authored
gh-111178: fix UBSan failures in Python/traceback.c (GH-128259)
1 parent 6bb03c7 commit ced296d

File tree

1 file changed

+26
-16
lines changed

1 file changed

+26
-16
lines changed

Python/traceback.c

Lines changed: 26 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ class traceback "PyTracebackObject *" "&PyTraceback_Type"
3838
[clinic start generated code]*/
3939
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=cf96294b2bebc811]*/
4040

41+
#define _PyTracebackObject_CAST(op) ((PyTracebackObject *)(op))
42+
4143
#include "clinic/traceback.c.h"
4244

4345
static PyObject *
@@ -91,15 +93,16 @@ tb_new_impl(PyTypeObject *type, PyObject *tb_next, PyFrameObject *tb_frame,
9193
}
9294

9395
static PyObject *
94-
tb_dir(PyTracebackObject *self, PyObject *Py_UNUSED(ignored))
96+
tb_dir(PyObject *Py_UNUSED(self), PyObject *Py_UNUSED(ignored))
9597
{
9698
return Py_BuildValue("[ssss]", "tb_frame", "tb_next",
9799
"tb_lasti", "tb_lineno");
98100
}
99101

100102
static PyObject *
101-
tb_next_get(PyTracebackObject *self, void *Py_UNUSED(_))
103+
tb_next_get(PyObject *op, void *Py_UNUSED(_))
102104
{
105+
PyTracebackObject *self = _PyTracebackObject_CAST(op);
103106
PyObject* ret = (PyObject*)self->tb_next;
104107
if (!ret) {
105108
ret = Py_None;
@@ -108,18 +111,21 @@ tb_next_get(PyTracebackObject *self, void *Py_UNUSED(_))
108111
}
109112

110113
static int
111-
tb_get_lineno(PyTracebackObject* tb) {
114+
tb_get_lineno(PyObject *op)
115+
{
116+
PyTracebackObject *tb = _PyTracebackObject_CAST(op);
112117
_PyInterpreterFrame* frame = tb->tb_frame->f_frame;
113118
assert(frame != NULL);
114119
return PyCode_Addr2Line(_PyFrame_GetCode(frame), tb->tb_lasti);
115120
}
116121

117122
static PyObject *
118-
tb_lineno_get(PyTracebackObject *self, void *Py_UNUSED(_))
123+
tb_lineno_get(PyObject *op, void *Py_UNUSED(_))
119124
{
125+
PyTracebackObject *self = _PyTracebackObject_CAST(op);
120126
int lineno = self->tb_lineno;
121127
if (lineno == -1) {
122-
lineno = tb_get_lineno(self);
128+
lineno = tb_get_lineno(op);
123129
if (lineno < 0) {
124130
Py_RETURN_NONE;
125131
}
@@ -128,7 +134,7 @@ tb_lineno_get(PyTracebackObject *self, void *Py_UNUSED(_))
128134
}
129135

130136
static int
131-
tb_next_set(PyTracebackObject *self, PyObject *new_next, void *Py_UNUSED(_))
137+
tb_next_set(PyObject *op, PyObject *new_next, void *Py_UNUSED(_))
132138
{
133139
if (!new_next) {
134140
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(_))
147153
}
148154

149155
/* Check for loops */
156+
PyTracebackObject *self = _PyTracebackObject_CAST(op);
150157
PyTracebackObject *cursor = (PyTracebackObject *)new_next;
151158
while (cursor) {
152159
if (cursor == self) {
@@ -163,7 +170,7 @@ tb_next_set(PyTracebackObject *self, PyObject *new_next, void *Py_UNUSED(_))
163170

164171

165172
static PyMethodDef tb_methods[] = {
166-
{"__dir__", _PyCFunction_CAST(tb_dir), METH_NOARGS},
173+
{"__dir__", tb_dir, METH_NOARGS, NULL},
167174
{NULL, NULL, 0, NULL},
168175
};
169176

@@ -174,14 +181,15 @@ static PyMemberDef tb_memberlist[] = {
174181
};
175182

176183
static PyGetSetDef tb_getsetters[] = {
177-
{"tb_next", (getter)tb_next_get, (setter)tb_next_set, NULL, NULL},
178-
{"tb_lineno", (getter)tb_lineno_get, NULL, NULL, NULL},
184+
{"tb_next", tb_next_get, tb_next_set, NULL, NULL},
185+
{"tb_lineno", tb_lineno_get, NULL, NULL, NULL},
179186
{NULL} /* Sentinel */
180187
};
181188

182189
static void
183-
tb_dealloc(PyTracebackObject *tb)
190+
tb_dealloc(PyObject *op)
184191
{
192+
PyTracebackObject *tb = _PyTracebackObject_CAST(op);
185193
PyObject_GC_UnTrack(tb);
186194
Py_TRASHCAN_BEGIN(tb, tb_dealloc)
187195
Py_XDECREF(tb->tb_next);
@@ -191,16 +199,18 @@ tb_dealloc(PyTracebackObject *tb)
191199
}
192200

193201
static int
194-
tb_traverse(PyTracebackObject *tb, visitproc visit, void *arg)
202+
tb_traverse(PyObject *op, visitproc visit, void *arg)
195203
{
204+
PyTracebackObject *tb = _PyTracebackObject_CAST(op);
196205
Py_VISIT(tb->tb_next);
197206
Py_VISIT(tb->tb_frame);
198207
return 0;
199208
}
200209

201210
static int
202-
tb_clear(PyTracebackObject *tb)
211+
tb_clear(PyObject *op)
203212
{
213+
PyTracebackObject *tb = _PyTracebackObject_CAST(op);
204214
Py_CLEAR(tb->tb_next);
205215
Py_CLEAR(tb->tb_frame);
206216
return 0;
@@ -211,7 +221,7 @@ PyTypeObject PyTraceBack_Type = {
211221
"traceback",
212222
sizeof(PyTracebackObject),
213223
0,
214-
(destructor)tb_dealloc, /*tp_dealloc*/
224+
tb_dealloc, /*tp_dealloc*/
215225
0, /*tp_vectorcall_offset*/
216226
0, /*tp_getattr*/
217227
0, /*tp_setattr*/
@@ -228,8 +238,8 @@ PyTypeObject PyTraceBack_Type = {
228238
0, /* tp_as_buffer */
229239
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
230240
tb_new__doc__, /* tp_doc */
231-
(traverseproc)tb_traverse, /* tp_traverse */
232-
(inquiry)tb_clear, /* tp_clear */
241+
tb_traverse, /* tp_traverse */
242+
tb_clear, /* tp_clear */
233243
0, /* tp_richcompare */
234244
0, /* tp_weaklistoffset */
235245
0, /* tp_iter */
@@ -663,7 +673,7 @@ tb_printinternal(PyTracebackObject *tb, PyObject *f, long limit)
663673
code = PyFrame_GetCode(tb->tb_frame);
664674
int tb_lineno = tb->tb_lineno;
665675
if (tb_lineno == -1) {
666-
tb_lineno = tb_get_lineno(tb);
676+
tb_lineno = tb_get_lineno((PyObject *)tb);
667677
}
668678
if (last_file == NULL ||
669679
code->co_filename != last_file ||

0 commit comments

Comments
 (0)