]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-107803: fix thread safety issue in double linked list implementation (#121007)
authorKumar Aditya <kumaraditya@python.org>
Wed, 26 Jun 2024 05:11:32 +0000 (10:41 +0530)
committerGitHub <noreply@github.com>
Wed, 26 Jun 2024 05:11:32 +0000 (05:11 +0000)
Include/internal/pycore_object.h
Modules/_asynciomodule.c

index 311f295685f361a8274dd56ec5a5eb52788da3b1..ebb0f30b5f73779c27754402646b45f89ef8fc7d 100644 (file)
@@ -126,8 +126,8 @@ static inline void _Py_RefcntAdd(PyObject* op, Py_ssize_t n)
 }
 #define _Py_RefcntAdd(op, n) _Py_RefcntAdd(_PyObject_CAST(op), n)
 
-extern void _Py_SetImmortal(PyObject *op);
-extern void _Py_SetImmortalUntracked(PyObject *op);
+PyAPI_FUNC(void) _Py_SetImmortal(PyObject *op);
+PyAPI_FUNC(void) _Py_SetImmortalUntracked(PyObject *op);
 
 // Makes an immortal object mortal again with the specified refcnt. Should only
 // be used during runtime finalization.
index 4672fc7f60efd62349045d2a17667e75a583b252..87ad236cdbb39f8ce807fa0c1433e85e9d80f550 100644 (file)
@@ -6,6 +6,7 @@
 #include "pycore_dict.h"          // _PyDict_GetItem_KnownHash()
 #include "pycore_modsupport.h"    // _PyArg_CheckPositional()
 #include "pycore_moduleobject.h"  // _PyModule_GetState()
+#include "pycore_object.h"        // _Py_SetImmortalUntracked
 #include "pycore_pyerrors.h"      // _PyErr_ClearExcState()
 #include "pycore_pylifecycle.h"   // _Py_IsInterpreterFinalizing()
 #include "pycore_pystate.h"       // _PyThreadState_GET()
@@ -3706,6 +3707,7 @@ _asyncio_all_tasks_impl(PyObject *module, PyObject *loop)
     }
     Py_DECREF(eager_iter);
     TaskObj *head = state->asyncio_tasks.head;
+    Py_INCREF(head);
     assert(head != NULL);
     assert(head->prev == NULL);
     TaskObj *tail = &state->asyncio_tasks.tail;
@@ -3714,10 +3716,11 @@ _asyncio_all_tasks_impl(PyObject *module, PyObject *loop)
         if (add_one_task(state, tasks, (PyObject *)head, loop) < 0) {
             Py_DECREF(tasks);
             Py_DECREF(loop);
+            Py_DECREF(head);
             return NULL;
         }
-        head = head->next;
-        assert(head != NULL);
+        Py_INCREF(head->next);
+        Py_SETREF(head, head->next);
     }
     PyObject *scheduled_iter = PyObject_GetIter(state->non_asyncio_tasks);
     if (scheduled_iter == NULL) {
@@ -3944,6 +3947,8 @@ static int
 module_exec(PyObject *mod)
 {
     asyncio_state *state = get_asyncio_state(mod);
+    Py_SET_TYPE(&state->asyncio_tasks.tail, state->TaskType);
+    _Py_SetImmortalUntracked((PyObject *)&state->asyncio_tasks.tail);
     state->asyncio_tasks.head = &state->asyncio_tasks.tail;
 
 #define CREATE_TYPE(m, tp, spec, base)                                  \