From 5d4d511d14c338d5a84153fe0aedcbd8a6d75335 Mon Sep 17 00:00:00 2001 From: Thomas Kowalski Date: Wed, 20 May 2026 15:16:27 +0200 Subject: [PATCH 1/6] fix: pickle whichmodule has a UAF on free-threading --- Modules/_pickle.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/Modules/_pickle.c b/Modules/_pickle.c index 15d95c658d6f90..7d39ed946d2e0a 100644 --- a/Modules/_pickle.c +++ b/Modules/_pickle.c @@ -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 (found_name != NULL) { + Py_DECREF(modules); + return found_name; + } + if (error) { + Py_DECREF(modules); + return NULL; + } } else { PyObject *iterator = PyObject_GetIter(modules); From 1fd7911d022c5e9371d0ae8a18fd788142dcf5e2 Mon Sep 17 00:00:00 2001 From: Thomas Kowalski Date: Thu, 21 May 2026 20:45:54 +0200 Subject: [PATCH 2/6] review: address comment on code order --- Modules/_pickle.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Modules/_pickle.c b/Modules/_pickle.c index 7d39ed946d2e0a..ae4daff9198db1 100644 --- a/Modules/_pickle.c +++ b/Modules/_pickle.c @@ -2075,14 +2075,14 @@ whichmodule(PickleState *st, PyObject *global, PyObject *global_name, PyObject * } } Py_END_CRITICAL_SECTION(); - if (found_name != NULL) { - Py_DECREF(modules); - return found_name; - } if (error) { Py_DECREF(modules); return NULL; } + if (found_name != NULL) { + Py_DECREF(modules); + return found_name; + } } else { PyObject *iterator = PyObject_GetIter(modules); From adea9625005aa3c3425d43f86c319a22e42456a8 Mon Sep 17 00:00:00 2001 From: Thomas Kowalski Date: Thu, 21 May 2026 20:48:48 +0200 Subject: [PATCH 3/6] misc: add news entry --- .../Library/2026-05-21-20-47-45.gh-issue-150157.ZvmO-bQZ.rst | 2 ++ 1 file changed, 2 insertions(+) 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 00000000000000..5d0db14943ff1b --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-05-21-20-47-45.gh-issue-150157.ZvmO-bQZ.rst @@ -0,0 +1,2 @@ +Fix a heap use-after-free in :mod:`pickle`\'s ``whichmodule`` on +free-threaded builds. Patch by Thomas Kowalski. From 3981cfcc9d18705c2aa79d5139c8ddafd395fa39 Mon Sep 17 00:00:00 2001 From: Thomas Kowalski Date: Sat, 30 May 2026 17:24:54 +0200 Subject: [PATCH 4/6] misc: update news entry --- .../Library/2026-05-21-20-47-45.gh-issue-150157.ZvmO-bQZ.rst | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) 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 index 5d0db14943ff1b..578a493ae648be 100644 --- 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 @@ -1,2 +1,3 @@ -Fix a heap use-after-free in :mod:`pickle`\'s ``whichmodule`` on -free-threaded builds. Patch by Thomas Kowalski. +Fix a potential crash occurring when pickling objects +concurrently in free-threaded builds. +Patch by Thomas Kowalski. From 012200c7eb5762651138e8bc6c306012d0d3f894 Mon Sep 17 00:00:00 2001 From: Thomas Kowalski Date: Sat, 30 May 2026 21:52:45 +0200 Subject: [PATCH 5/6] misc: update news entry --- .../2026-05-21-20-47-45.gh-issue-150157.ZvmO-bQZ.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) 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 index 578a493ae648be..7c330827c1cc14 100644 --- 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 @@ -1,3 +1,3 @@ -Fix a potential crash occurring when pickling objects -concurrently in free-threaded builds. -Patch by Thomas Kowalski. +Fix a crash in free-threaded builds that occurs when pickling +an object without a ``__module__`` attribute while :data:`sys.modules` +is concurrently being modified. From 49b9a1f6b6f2a7a2e60a58c481fb4a502e011dd8 Mon Sep 17 00:00:00 2001 From: Thomas Kowalski Date: Sun, 31 May 2026 19:56:01 +0200 Subject: [PATCH 6/6] misc: update news entry --- .../Library/2026-05-21-20-47-45.gh-issue-150157.ZvmO-bQZ.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 index 7c330827c1cc14..3a12e26cf736f7 100644 --- 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 @@ -1,3 +1,3 @@ -Fix a crash in free-threaded builds that occurs when pickling -an object without a ``__module__`` attribute while :data:`sys.modules` +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.