From 23a764aef034987075ffec561f5d69f40e30c09c Mon Sep 17 00:00:00 2001 From: Thomas Kowalski Date: Mon, 1 Jun 2026 16:32:13 +0200 Subject: [PATCH] gh-150157: Fix critical section for PyDict_Next() in _pickle.c (GH-150158) (cherry picked from commit c5516e7e371f7b273eb37c7b65f14ef14ee81f11) Co-authored-by: Thomas Kowalski --- ...5-21-20-47-45.gh-issue-150157.ZvmO-bQZ.rst | 3 +++ Modules/_pickle.c | 20 +++++++++++++++---- 2 files changed, 19 insertions(+), 4 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2026-05-21-20-47-45.gh-issue-150157.ZvmO-bQZ.rst diff --git a/Misc/NEWS.d/next/Library/2026-05-21-20-47-45.gh-issue-150157.ZvmO-bQZ.rst b/Misc/NEWS.d/next/Library/2026-05-21-20-47-45.gh-issue-150157.ZvmO-bQZ.rst new file mode 100644 index 000000000000000..3a12e26cf736f79 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-05-21-20-47-45.gh-issue-150157.ZvmO-bQZ.rst @@ -0,0 +1,3 @@ +Fix a crash in free-threaded builds that occurs when pickling by name +objects without a ``__module__`` attribute while :data:`sys.modules` +is concurrently being modified. diff --git a/Modules/_pickle.c b/Modules/_pickle.c index 75e1c4dea85e004..9a6f24ec8649630 100644 --- a/Modules/_pickle.c +++ b/Modules/_pickle.c @@ -1947,22 +1947,34 @@ whichmodule(PickleState *st, PyObject *global, PyObject *global_name, PyObject * return NULL; } if (PyDict_CheckExact(modules)) { + PyObject *found_name = NULL; + int error = 0; i = 0; + Py_BEGIN_CRITICAL_SECTION(modules); while (PyDict_Next(modules, &i, &module_name, &module)) { Py_INCREF(module_name); Py_INCREF(module); if (_checkmodule(module_name, module, global, dotted_path) == 0) { Py_DECREF(module); - Py_DECREF(modules); - return module_name; + found_name = module_name; + break; } Py_DECREF(module); Py_DECREF(module_name); if (PyErr_Occurred()) { - Py_DECREF(modules); - return NULL; + error = 1; + break; } } + Py_END_CRITICAL_SECTION(); + if (error) { + Py_DECREF(modules); + return NULL; + } + if (found_name != NULL) { + Py_DECREF(modules); + return found_name; + } } else { PyObject *iterator = PyObject_GetIter(modules);