mirror of
https://github.com/python/cpython.git
synced 2025-09-09 18:32:22 +00:00
gh-111178: fix UBSan failures in Python/traceback.c
(GH-128259)
This commit is contained in:
parent
6bb03c7490
commit
ced296d2c0
1 changed files with 26 additions and 16 deletions
|
@ -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 ||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue