@@ -264,7 +264,38 @@ static PyObject *
264264atexit_ncallbacks (PyObject * module , PyObject * unused )
265265{
266266 struct atexit_state * state = get_atexit_state ();
267+ <<<<<<< HEAD
267268 return PyLong_FromSsize_t (state -> ncallbacks );
269+ = == == ==
270+ assert (state -> callbacks != NULL );
271+ assert (PyList_CheckExact (state -> callbacks ));
272+ return PyLong_FromSsize_t (PyList_GET_SIZE (state -> callbacks ));
273+ }
274+
275+ static int
276+ atexit_unregister_locked (PyObject * callbacks , PyObject * func )
277+ {
278+ for (Py_ssize_t i = 0 ; i < PyList_GET_SIZE (callbacks ); ++ i ) {
279+ PyObject * tuple = Py_NewRef (PyList_GET_ITEM (callbacks , i ));
280+ assert (PyTuple_CheckExact (tuple ));
281+ PyObject * to_compare = PyTuple_GET_ITEM (tuple , 0 );
282+ int cmp = PyObject_RichCompareBool (func , to_compare , Py_EQ );
283+ Py_DECREF (tuple );
284+ if (cmp < 0 )
285+ {
286+ return -1 ;
287+ }
288+ if (cmp == 1 ) {
289+ // We found a callback!
290+ if (PyList_SetSlice (callbacks , i , i + 1 , NULL ) < 0 ) {
291+ return -1 ;
292+ }
293+ -- i ;
294+ }
295+ }
296+
297+ return 0 ;
298+ >>>>>>> 2b 466 c47c33 (gh - 112127 : Fix possible use - after - free in atexit .unregister () (GH - 114092 ))
268299}
269300
270301PyDoc_STRVAR (atexit_unregister__doc__ ,
@@ -287,7 +318,9 @@ atexit_unregister(PyObject *module, PyObject *func)
287318 continue ;
288319 }
289320
290- int eq = PyObject_RichCompareBool (cb -> func , func , Py_EQ );
321+ PyObject * to_compare = Py_NewRef (cb -> func );
322+ int eq = PyObject_RichCompareBool (to_compare , func , Py_EQ );
323+ Py_DECREF (to_compare );
291324 if (eq < 0 ) {
292325 return NULL ;
293326 }
0 commit comments