From d926271d75534586e69c8fbbd5a84b7eaeca4c3f Mon Sep 17 00:00:00 2001 From: Krishna-web-hub Date: Thu, 5 Mar 2026 10:46:42 +0000 Subject: [PATCH 1/3] gh-142572: Fix data race when accessing func_code in PyFunctionObject --- .../2026-03-05-12-01-44.gh-issue-145272.MeSSbg.rst | 1 + Objects/funcobject.c | 10 +++++++--- 2 files changed, 8 insertions(+), 3 deletions(-) create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-03-05-12-01-44.gh-issue-145272.MeSSbg.rst diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-05-12-01-44.gh-issue-145272.MeSSbg.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-03-05-12-01-44.gh-issue-145272.MeSSbg.rst new file mode 100644 index 00000000000000..74ba9e58892827 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-03-05-12-01-44.gh-issue-145272.MeSSbg.rst @@ -0,0 +1 @@ +Fixing race condition in PyFunctionObject.func_code diff --git a/Objects/funcobject.c b/Objects/funcobject.c index efe27a2b70c4de..fb977dfb31e8be 100644 --- a/Objects/funcobject.c +++ b/Objects/funcobject.c @@ -631,7 +631,8 @@ func_get_code(PyObject *self, void *Py_UNUSED(ignored)) return NULL; } - return Py_NewRef(op->func_code); + PyCodeObject *code = _Py_atomic_load_ptr(&op->func_code); + return Py_NewRef(code); } static int @@ -664,7 +665,7 @@ func_set_code(PyObject *self, PyObject *value, void *Py_UNUSED(ignored)) return -1; } - PyObject *func_code = PyFunction_GET_CODE(op); + PyCodeObject *func_code = _Py_atomic_load_ptr(&op->func_code); int old_flags = ((PyCodeObject *)func_code)->co_flags; int new_flags = ((PyCodeObject *)value)->co_flags; int mask = CO_GENERATOR | CO_COROUTINE | CO_ASYNC_GENERATOR; @@ -679,7 +680,10 @@ func_set_code(PyObject *self, PyObject *value, void *Py_UNUSED(ignored)) handle_func_event(PyFunction_EVENT_MODIFY_CODE, op, value); _PyFunction_ClearVersion(op); - Py_XSETREF(op->func_code, Py_NewRef(value)); + PyCodeObject *new = (PyCodeObject *)Py_NewRef(value); + PyCodeObject *old = + (PyCodeObject *)_Py_atomic_exchange_ptr(&op->func_code, new); + Py_XDECREF(old); return 0; } From 7b1032048abf3947cb24313cd6f1892dad77b101 Mon Sep 17 00:00:00 2001 From: Krishna-web-hub Date: Fri, 6 Mar 2026 12:05:14 +0000 Subject: [PATCH 2/3] Fix data race on func_code in free-threaded Python --- Include/cpython/funcobject.h | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/Include/cpython/funcobject.h b/Include/cpython/funcobject.h index 9e1599a7648564..6365b2c2074949 100644 --- a/Include/cpython/funcobject.h +++ b/Include/cpython/funcobject.h @@ -88,10 +88,13 @@ PyAPI_FUNC(int) PyFunction_SetAnnotations(PyObject *, PyObject *); /* Static inline functions for direct access to these values. Type checks are *not* done, so use with care. */ static inline PyObject* PyFunction_GET_CODE(PyObject *func) { - return _PyFunction_CAST(func)->func_code; + PyFunctionObject *op = _PyFunction_CAST(func); +#ifdef Py_GIL_DISABLED + return (PyObject *)_Py_atomic_load_ptr(&op->func_code); +#else + return op->func_code; +#endif } -#define PyFunction_GET_CODE(func) PyFunction_GET_CODE(_PyObject_CAST(func)) - static inline PyObject* PyFunction_GET_GLOBALS(PyObject *func) { return _PyFunction_CAST(func)->func_globals; } From e70399567d6555f27a4c87f586824bde097ca12a Mon Sep 17 00:00:00 2001 From: Krishna-web-hub Date: Fri, 6 Mar 2026 20:41:26 +0000 Subject: [PATCH 3/3] Fixing the issues --- Include/cpython/funcobject.h | 1 + Objects/funcobject.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Include/cpython/funcobject.h b/Include/cpython/funcobject.h index 6365b2c2074949..5e8f3c6e7f0c8a 100644 --- a/Include/cpython/funcobject.h +++ b/Include/cpython/funcobject.h @@ -95,6 +95,7 @@ static inline PyObject* PyFunction_GET_CODE(PyObject *func) { return op->func_code; #endif } +#define PyFunction_GET_CODE(func) PyFunction_GET_CODE(_PyObject_CAST(func)) static inline PyObject* PyFunction_GET_GLOBALS(PyObject *func) { return _PyFunction_CAST(func)->func_globals; } diff --git a/Objects/funcobject.c b/Objects/funcobject.c index fb977dfb31e8be..a77de332ac6ec5 100644 --- a/Objects/funcobject.c +++ b/Objects/funcobject.c @@ -665,7 +665,7 @@ func_set_code(PyObject *self, PyObject *value, void *Py_UNUSED(ignored)) return -1; } - PyCodeObject *func_code = _Py_atomic_load_ptr(&op->func_code); + PyCodeObject *func_code = (PyCodeObject *)PyFunction_GET_CODE(op); int old_flags = ((PyCodeObject *)func_code)->co_flags; int new_flags = ((PyCodeObject *)value)->co_flags; int mask = CO_GENERATOR | CO_COROUTINE | CO_ASYNC_GENERATOR;