]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-150157: Fix critical section for PyDict_Next() in _pickle.c (GH-150158)
authorThomas Kowalski <thom.kowa@gmail.com>
Mon, 1 Jun 2026 14:32:13 +0000 (16:32 +0200)
committerGitHub <noreply@github.com>
Mon, 1 Jun 2026 14:32:13 +0000 (17:32 +0300)
Misc/NEWS.d/next/Library/2026-05-21-20-47-45.gh-issue-150157.ZvmO-bQZ.rst [new file with mode: 0644]
Modules/_pickle.c

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 (file)
index 0000000..3a12e26
--- /dev/null
@@ -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.
index 2d82438f0d308d993eb48fe1b6851c96a94bc4ae..a5595be251a738d1dabb317e5aab3cbfee920a81 100644 (file)
@@ -2055,22 +2055,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);