mirror of
https://github.com/python/cpython.git
synced 2025-08-23 18:24:46 +00:00
gh-128421: add critical section around traceback.tb_next
(#131322)
This commit is contained in:
parent
b12af0a48f
commit
39b37b0110
2 changed files with 82 additions and 14 deletions
53
Python/clinic/traceback.c.h
generated
53
Python/clinic/traceback.c.h
generated
|
@ -6,6 +6,7 @@ preserve
|
||||||
# include "pycore_gc.h" // PyGC_Head
|
# include "pycore_gc.h" // PyGC_Head
|
||||||
# include "pycore_runtime.h" // _Py_ID()
|
# include "pycore_runtime.h" // _Py_ID()
|
||||||
#endif
|
#endif
|
||||||
|
#include "pycore_critical_section.h"// Py_BEGIN_CRITICAL_SECTION()
|
||||||
#include "pycore_modsupport.h" // _PyArg_UnpackKeywords()
|
#include "pycore_modsupport.h" // _PyArg_UnpackKeywords()
|
||||||
|
|
||||||
PyDoc_STRVAR(tb_new__doc__,
|
PyDoc_STRVAR(tb_new__doc__,
|
||||||
|
@ -79,4 +80,54 @@ tb_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
|
||||||
exit:
|
exit:
|
||||||
return return_value;
|
return return_value;
|
||||||
}
|
}
|
||||||
/*[clinic end generated code: output=62ebc0196940f663 input=a9049054013a1b77]*/
|
|
||||||
|
#if !defined(traceback_tb_next_DOCSTR)
|
||||||
|
# define traceback_tb_next_DOCSTR NULL
|
||||||
|
#endif
|
||||||
|
#if defined(TRACEBACK_TB_NEXT_GETSETDEF)
|
||||||
|
# undef TRACEBACK_TB_NEXT_GETSETDEF
|
||||||
|
# define TRACEBACK_TB_NEXT_GETSETDEF {"tb_next", (getter)traceback_tb_next_get, (setter)traceback_tb_next_set, traceback_tb_next_DOCSTR},
|
||||||
|
#else
|
||||||
|
# define TRACEBACK_TB_NEXT_GETSETDEF {"tb_next", (getter)traceback_tb_next_get, NULL, traceback_tb_next_DOCSTR},
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
traceback_tb_next_get_impl(PyTracebackObject *self);
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
traceback_tb_next_get(PyObject *self, void *Py_UNUSED(context))
|
||||||
|
{
|
||||||
|
PyObject *return_value = NULL;
|
||||||
|
|
||||||
|
Py_BEGIN_CRITICAL_SECTION(self);
|
||||||
|
return_value = traceback_tb_next_get_impl((PyTracebackObject *)self);
|
||||||
|
Py_END_CRITICAL_SECTION();
|
||||||
|
|
||||||
|
return return_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if !defined(traceback_tb_next_DOCSTR)
|
||||||
|
# define traceback_tb_next_DOCSTR NULL
|
||||||
|
#endif
|
||||||
|
#if defined(TRACEBACK_TB_NEXT_GETSETDEF)
|
||||||
|
# undef TRACEBACK_TB_NEXT_GETSETDEF
|
||||||
|
# define TRACEBACK_TB_NEXT_GETSETDEF {"tb_next", (getter)traceback_tb_next_get, (setter)traceback_tb_next_set, traceback_tb_next_DOCSTR},
|
||||||
|
#else
|
||||||
|
# define TRACEBACK_TB_NEXT_GETSETDEF {"tb_next", NULL, (setter)traceback_tb_next_set, NULL},
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static int
|
||||||
|
traceback_tb_next_set_impl(PyTracebackObject *self, PyObject *value);
|
||||||
|
|
||||||
|
static int
|
||||||
|
traceback_tb_next_set(PyObject *self, PyObject *value, void *Py_UNUSED(context))
|
||||||
|
{
|
||||||
|
int return_value;
|
||||||
|
|
||||||
|
Py_BEGIN_CRITICAL_SECTION(self);
|
||||||
|
return_value = traceback_tb_next_set_impl((PyTracebackObject *)self, value);
|
||||||
|
Py_END_CRITICAL_SECTION();
|
||||||
|
|
||||||
|
return return_value;
|
||||||
|
}
|
||||||
|
/*[clinic end generated code: output=ca43786e235e38f4 input=a9049054013a1b77]*/
|
||||||
|
|
|
@ -99,10 +99,16 @@ tb_dir(PyObject *Py_UNUSED(self), PyObject *Py_UNUSED(ignored))
|
||||||
"tb_lasti", "tb_lineno");
|
"tb_lasti", "tb_lineno");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*[clinic input]
|
||||||
|
@critical_section
|
||||||
|
@getter
|
||||||
|
traceback.tb_next
|
||||||
|
[clinic start generated code]*/
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
tb_next_get(PyObject *op, void *Py_UNUSED(_))
|
traceback_tb_next_get_impl(PyTracebackObject *self)
|
||||||
|
/*[clinic end generated code: output=963634df7d5fc837 input=8f6345f2b73cb965]*/
|
||||||
{
|
{
|
||||||
PyTracebackObject *self = _PyTracebackObject_CAST(op);
|
|
||||||
PyObject* ret = (PyObject*)self->tb_next;
|
PyObject* ret = (PyObject*)self->tb_next;
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
ret = Py_None;
|
ret = Py_None;
|
||||||
|
@ -133,37 +139,48 @@ tb_lineno_get(PyObject *op, void *Py_UNUSED(_))
|
||||||
return PyLong_FromLong(lineno);
|
return PyLong_FromLong(lineno);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*[clinic input]
|
||||||
|
@critical_section
|
||||||
|
@setter
|
||||||
|
traceback.tb_next
|
||||||
|
[clinic start generated code]*/
|
||||||
|
|
||||||
static int
|
static int
|
||||||
tb_next_set(PyObject *op, PyObject *new_next, void *Py_UNUSED(_))
|
traceback_tb_next_set_impl(PyTracebackObject *self, PyObject *value)
|
||||||
|
/*[clinic end generated code: output=d4868cbc48f2adac input=ce66367f85e3c443]*/
|
||||||
{
|
{
|
||||||
if (!new_next) {
|
if (!value) {
|
||||||
PyErr_Format(PyExc_TypeError, "can't delete tb_next attribute");
|
PyErr_Format(PyExc_TypeError, "can't delete tb_next attribute");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We accept None or a traceback object, and map None -> NULL (inverse of
|
/* We accept None or a traceback object, and map None -> NULL (inverse of
|
||||||
tb_next_get) */
|
tb_next_get) */
|
||||||
if (new_next == Py_None) {
|
if (value == Py_None) {
|
||||||
new_next = NULL;
|
value = NULL;
|
||||||
} else if (!PyTraceBack_Check(new_next)) {
|
} else if (!PyTraceBack_Check(value)) {
|
||||||
PyErr_Format(PyExc_TypeError,
|
PyErr_Format(PyExc_TypeError,
|
||||||
"expected traceback object, got '%s'",
|
"expected traceback object, got '%s'",
|
||||||
Py_TYPE(new_next)->tp_name);
|
Py_TYPE(value)->tp_name);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check for loops */
|
/* Check for loops */
|
||||||
PyTracebackObject *self = _PyTracebackObject_CAST(op);
|
PyTracebackObject *cursor = (PyTracebackObject *)value;
|
||||||
PyTracebackObject *cursor = (PyTracebackObject *)new_next;
|
Py_XINCREF(cursor);
|
||||||
while (cursor) {
|
while (cursor) {
|
||||||
if (cursor == self) {
|
if (cursor == self) {
|
||||||
PyErr_Format(PyExc_ValueError, "traceback loop detected");
|
PyErr_Format(PyExc_ValueError, "traceback loop detected");
|
||||||
|
Py_DECREF(cursor);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
cursor = cursor->tb_next;
|
Py_BEGIN_CRITICAL_SECTION(cursor);
|
||||||
|
Py_XINCREF(cursor->tb_next);
|
||||||
|
Py_SETREF(cursor, cursor->tb_next);
|
||||||
|
Py_END_CRITICAL_SECTION();
|
||||||
}
|
}
|
||||||
|
|
||||||
Py_XSETREF(self->tb_next, (PyTracebackObject *)Py_XNewRef(new_next));
|
Py_XSETREF(self->tb_next, (PyTracebackObject *)Py_XNewRef(value));
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -181,7 +198,7 @@ static PyMemberDef tb_memberlist[] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
static PyGetSetDef tb_getsetters[] = {
|
static PyGetSetDef tb_getsetters[] = {
|
||||||
{"tb_next", tb_next_get, tb_next_set, NULL, NULL},
|
TRACEBACK_TB_NEXT_GETSETDEF
|
||||||
{"tb_lineno", tb_lineno_get, NULL, NULL, NULL},
|
{"tb_lineno", tb_lineno_get, NULL, NULL, NULL},
|
||||||
{NULL} /* Sentinel */
|
{NULL} /* Sentinel */
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue