gh-128421: add critical section around `traceback.tb_next` (#131322) · python/cpython@39b37b0

GitHub

@@ -99,10 +99,16 @@ tb_dir(PyObject *Py_UNUSED(self), PyObject *Py_UNUSED(ignored))

9999"tb_lasti", "tb_lineno");

100100}

101101102+/*[clinic input]

103+@critical_section

104+@getter

105+traceback.tb_next

106+[clinic start generated code]*/

107+102108staticPyObject*

103-tb_next_get(PyObject*op, void*Py_UNUSED(_))

109+traceback_tb_next_get_impl(PyTracebackObject*self)

110+/*[clinic end generated code: output=963634df7d5fc837 input=8f6345f2b73cb965]*/

104111{

105-PyTracebackObject*self=_PyTracebackObject_CAST(op);

106112PyObject*ret= (PyObject*)self->tb_next;

107113if (!ret) {

108114ret=Py_None;

@@ -133,37 +139,48 @@ tb_lineno_get(PyObject *op, void *Py_UNUSED(_))

133139returnPyLong_FromLong(lineno);

134140}

135141142+/*[clinic input]

143+@critical_section

144+@setter

145+traceback.tb_next

146+[clinic start generated code]*/

147+136148staticint

137-tb_next_set(PyObject*op, PyObject*new_next, void*Py_UNUSED(_))

149+traceback_tb_next_set_impl(PyTracebackObject*self, PyObject*value)

150+/*[clinic end generated code: output=d4868cbc48f2adac input=ce66367f85e3c443]*/

138151{

139-if (!new_next) {

152+if (!value) {

140153PyErr_Format(PyExc_TypeError, "can't delete tb_next attribute");

141154return-1;

142155 }

143156144157/* We accept None or a traceback object, and map None -> NULL (inverse of

145158 tb_next_get) */

146-if (new_next==Py_None) {

147-new_next=NULL;

148- } elseif (!PyTraceBack_Check(new_next)) {

159+if (value==Py_None) {

160+value=NULL;

161+ } elseif (!PyTraceBack_Check(value)) {

149162PyErr_Format(PyExc_TypeError,

150163"expected traceback object, got '%s'",

151-Py_TYPE(new_next)->tp_name);

164+Py_TYPE(value)->tp_name);

152165return-1;

153166 }

154167155168/* Check for loops */

156-PyTracebackObject*self=_PyTracebackObject_CAST(op);

157-PyTracebackObject*cursor= (PyTracebackObject*)new_next;

169+PyTracebackObject*cursor=(PyTracebackObject*)value;

170+Py_XINCREF(cursor);

158171while (cursor) {

159172if (cursor==self) {

160173PyErr_Format(PyExc_ValueError, "traceback loop detected");

174+Py_DECREF(cursor);

161175return-1;

162176 }

163-cursor=cursor->tb_next;

177+Py_BEGIN_CRITICAL_SECTION(cursor);

178+Py_XINCREF(cursor->tb_next);

179+Py_SETREF(cursor, cursor->tb_next);

180+Py_END_CRITICAL_SECTION();

164181 }

165182166-Py_XSETREF(self->tb_next, (PyTracebackObject*)Py_XNewRef(new_next));

183+Py_XSETREF(self->tb_next, (PyTracebackObject*)Py_XNewRef(value));

167184168185return0;

169186}

@@ -181,7 +198,7 @@ static PyMemberDef tb_memberlist[] = {

181198};

182199183200staticPyGetSetDeftb_getsetters[] = {

184-{"tb_next", tb_next_get, tb_next_set, NULL, NULL},

201+TRACEBACK_TB_NEXT_GETSETDEF

185202 {"tb_lineno", tb_lineno_get, NULL, NULL, NULL},

186203 {NULL} /* Sentinel */

187204};