mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 21:51:50 +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_runtime.h"     // _Py_ID()
 | ||||
| #endif | ||||
| #include "pycore_critical_section.h"// Py_BEGIN_CRITICAL_SECTION() | ||||
| #include "pycore_modsupport.h"    // _PyArg_UnpackKeywords() | ||||
| 
 | ||||
| PyDoc_STRVAR(tb_new__doc__, | ||||
|  | @ -79,4 +80,54 @@ tb_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) | |||
| exit: | ||||
|     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"); | ||||
| } | ||||
| 
 | ||||
| /*[clinic input]
 | ||||
| @critical_section | ||||
| @getter | ||||
| traceback.tb_next | ||||
| [clinic start generated code]*/ | ||||
| 
 | ||||
| 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; | ||||
|     if (!ret) { | ||||
|         ret = Py_None; | ||||
|  | @ -133,37 +139,48 @@ tb_lineno_get(PyObject *op, void *Py_UNUSED(_)) | |||
|     return PyLong_FromLong(lineno); | ||||
| } | ||||
| 
 | ||||
| /*[clinic input]
 | ||||
| @critical_section | ||||
| @setter | ||||
| traceback.tb_next | ||||
| [clinic start generated code]*/ | ||||
| 
 | ||||
| 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"); | ||||
|         return -1; | ||||
|     } | ||||
| 
 | ||||
|     /* We accept None or a traceback object, and map None -> NULL (inverse of
 | ||||
|        tb_next_get) */ | ||||
|     if (new_next == Py_None) { | ||||
|         new_next = NULL; | ||||
|     } else if (!PyTraceBack_Check(new_next)) { | ||||
|     if (value == Py_None) { | ||||
|         value = NULL; | ||||
|     } else if (!PyTraceBack_Check(value)) { | ||||
|         PyErr_Format(PyExc_TypeError, | ||||
|                      "expected traceback object, got '%s'", | ||||
|                      Py_TYPE(new_next)->tp_name); | ||||
|                      Py_TYPE(value)->tp_name); | ||||
|         return -1; | ||||
|     } | ||||
| 
 | ||||
|     /* Check for loops */ | ||||
|     PyTracebackObject *self = _PyTracebackObject_CAST(op); | ||||
|     PyTracebackObject *cursor = (PyTracebackObject *)new_next; | ||||
|     PyTracebackObject *cursor = (PyTracebackObject *)value; | ||||
|     Py_XINCREF(cursor); | ||||
|     while (cursor) { | ||||
|         if (cursor == self) { | ||||
|             PyErr_Format(PyExc_ValueError, "traceback loop detected"); | ||||
|             Py_DECREF(cursor); | ||||
|             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; | ||||
| } | ||||
|  | @ -181,7 +198,7 @@ static PyMemberDef tb_memberlist[] = { | |||
| }; | ||||
| 
 | ||||
| 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}, | ||||
|     {NULL}      /* Sentinel */ | ||||
| }; | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Kumar Aditya
						Kumar Aditya