mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 05:31:20 +00:00 
			
		
		
		
	bpo-46417: Fix race condition on setting type __bases__ (GH-30788) (GH-30790)
Fix a race condition on setting a type __bases__ attribute: the
internal function add_subclass() now gets the
PyTypeObject.tp_subclasses member after calling PyWeakref_NewRef()
which can trigger a garbage collection which can indirectly modify
PyTypeObject.tp_subclasses.
(cherry picked from commit f1c6ae3270)
Co-authored-by: Victor Stinner <vstinner@python.org>
Co-authored-by: Victor Stinner <vstinner@python.org>
			
			
This commit is contained in:
		
							parent
							
								
									6ed874f8c5
								
							
						
					
					
						commit
						f1796f2947
					
				
					 2 changed files with 21 additions and 11 deletions
				
			
		|  | @ -0,0 +1,5 @@ | ||||||
|  | Fix a race condition on setting a type ``__bases__`` attribute: the internal | ||||||
|  | function ``add_subclass()`` now gets the ``PyTypeObject.tp_subclasses`` | ||||||
|  | member after calling :c:func:`PyWeakref_NewRef` which can trigger a garbage | ||||||
|  | collection which can indirectly modify ``PyTypeObject.tp_subclasses``. Patch | ||||||
|  | by Victor Stinner. | ||||||
|  | @ -5622,24 +5622,29 @@ PyType_Ready(PyTypeObject *type) | ||||||
| static int | static int | ||||||
| add_subclass(PyTypeObject *base, PyTypeObject *type) | add_subclass(PyTypeObject *base, PyTypeObject *type) | ||||||
| { | { | ||||||
|     int result = -1; |     PyObject *key = PyLong_FromVoidPtr((void *) type); | ||||||
|     PyObject *dict, *key, *newobj; |     if (key == NULL) | ||||||
|  |         return -1; | ||||||
| 
 | 
 | ||||||
|     dict = base->tp_subclasses; |     PyObject *ref = PyWeakref_NewRef((PyObject *)type, NULL); | ||||||
|  |     if (ref == NULL) { | ||||||
|  |         Py_DECREF(key); | ||||||
|  |         return -1; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // Only get tp_subclasses after creating the key and value.
 | ||||||
|  |     // PyWeakref_NewRef() can trigger a garbage collection which can execute
 | ||||||
|  |     // arbitrary Python code and so modify base->tp_subclasses.
 | ||||||
|  |     PyObject *dict = base->tp_subclasses; | ||||||
|     if (dict == NULL) { |     if (dict == NULL) { | ||||||
|         base->tp_subclasses = dict = PyDict_New(); |         base->tp_subclasses = dict = PyDict_New(); | ||||||
|         if (dict == NULL) |         if (dict == NULL) | ||||||
|             return -1; |             return -1; | ||||||
|     } |     } | ||||||
|     assert(PyDict_CheckExact(dict)); |     assert(PyDict_CheckExact(dict)); | ||||||
|     key = PyLong_FromVoidPtr((void *) type); | 
 | ||||||
|     if (key == NULL) |     int result = PyDict_SetItem(dict, key, ref); | ||||||
|         return -1; |     Py_DECREF(ref); | ||||||
|     newobj = PyWeakref_NewRef((PyObject *)type, NULL); |  | ||||||
|     if (newobj != NULL) { |  | ||||||
|         result = PyDict_SetItem(dict, key, newobj); |  | ||||||
|         Py_DECREF(newobj); |  | ||||||
|     } |  | ||||||
|     Py_DECREF(key); |     Py_DECREF(key); | ||||||
|     return result; |     return result; | ||||||
| } | } | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Miss Islington (bot)
						Miss Islington (bot)