From 70671267c11c562c6ca682eebf863616b258c20a Mon Sep 17 00:00:00 2001 From: dr-carlos <77367421+dr-carlos@users.noreply.github.com> Date: Wed, 10 Dec 2025 17:01:57 +1030 Subject: [PATCH 1/2] gh-142029: Raise `ValueError` instead of crashing on empty name given to `create_builtin()` (#142033) Co-authored-by: Victor Stinner --- Lib/test/test_import/__init__.py | 14 ++++++++++++++ .../2025-11-28-16-45-07.gh-issue-142029.JuXiKu.rst | 2 ++ Python/import.c | 6 ++++++ 3 files changed, 22 insertions(+) create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2025-11-28-16-45-07.gh-issue-142029.JuXiKu.rst diff --git a/Lib/test/test_import/__init__.py b/Lib/test/test_import/__init__.py index 271361ae816449..fa4f5e013d4b17 100644 --- a/Lib/test/test_import/__init__.py +++ b/Lib/test/test_import/__init__.py @@ -1253,6 +1253,20 @@ class Spec2: origin = "a\x00b" _imp.create_dynamic(Spec2()) + def test_create_builtin(self): + class Spec: + name = None + spec = Spec() + + with self.assertRaisesRegex(TypeError, 'name must be string, not NoneType'): + _imp.create_builtin(spec) + + spec.name = "" + + # gh-142029 + with self.assertRaisesRegex(ValueError, 'name must not be empty'): + _imp.create_builtin(spec) + def test_filter_syntax_warnings_by_module(self): module_re = r'test\.test_import\.data\.syntax_warnings\z' unload('test.test_import.data.syntax_warnings') diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-11-28-16-45-07.gh-issue-142029.JuXiKu.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-11-28-16-45-07.gh-issue-142029.JuXiKu.rst new file mode 100644 index 00000000000000..b4cd284804de98 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2025-11-28-16-45-07.gh-issue-142029.JuXiKu.rst @@ -0,0 +1,2 @@ +Raise :exc:`ValueError` instead of crashing when empty string is used as a name +in ``_imp.create_builtin()``. diff --git a/Python/import.c b/Python/import.c index e91c95b40d94bf..4dd247fac27654 100644 --- a/Python/import.c +++ b/Python/import.c @@ -4420,6 +4420,12 @@ _imp_create_builtin(PyObject *module, PyObject *spec) return NULL; } + if (PyUnicode_GetLength(name) == 0) { + PyErr_Format(PyExc_ValueError, "name must not be empty"); + Py_DECREF(name); + return NULL; + } + PyObject *mod = create_builtin(tstate, name, spec, NULL); Py_DECREF(name); return mod; From 49b1fb43f65290dadeb83ed6f7c0c74995fda7a1 Mon Sep 17 00:00:00 2001 From: Kevin Wang Date: Wed, 10 Dec 2025 02:29:40 -0500 Subject: [PATCH 2/2] gh-142048: Fix lost gc allocations count on thread cleanup (#142233) --- Python/pystate.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/Python/pystate.c b/Python/pystate.c index 2956e785405a0e..4bf89a234266e4 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -1765,16 +1765,23 @@ PyThreadState_Clear(PyThreadState *tstate) struct _Py_freelists *freelists = _Py_freelists_GET(); _PyObject_ClearFreeLists(freelists, 1); + // Flush the thread's local GC allocation count to the global count + // before the thread state is cleared, otherwise the count is lost. + _PyThreadStateImpl *tstate_impl = (_PyThreadStateImpl *)tstate; + _Py_atomic_add_int(&tstate->interp->gc.young.count, + (int)tstate_impl->gc.alloc_count); + tstate_impl->gc.alloc_count = 0; + // Merge our thread-local refcounts into the type's own refcount and // free our local refcount array. - _PyObject_FinalizePerThreadRefcounts((_PyThreadStateImpl *)tstate); + _PyObject_FinalizePerThreadRefcounts(tstate_impl); // Remove ourself from the biased reference counting table of threads. _Py_brc_remove_thread(tstate); // Release our thread-local copies of the bytecode for reuse by another // thread - _Py_ClearTLBCIndex((_PyThreadStateImpl *)tstate); + _Py_ClearTLBCIndex(tstate_impl); #endif // Merge our queue of pointers to be freed into the interpreter queue.