From cd2ca74c53d3cb502db40e3f52911d4429797daf Mon Sep 17 00:00:00 2001 From: dr-carlos <77367421+dr-carlos@users.noreply.github.com> Date: Mon, 15 Dec 2025 22:50:19 +1030 Subject: [PATCH] gh-142029: Raise `ModuleNotFoundError` instead of crashing on nonexsistent module name given to `create_builtin()` (#142054) Co-authored-by: Brett Cannon Co-authored-by: Victor Stinner --- Lib/test/test_import/__init__.py | 12 +++++-- ...-11-29-08-51-56.gh-issue-142029.rUpcmt.rst | 2 ++ Python/import.c | 32 +++++++++++++------ 3 files changed, 34 insertions(+), 12 deletions(-) create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2025-11-29-08-51-56.gh-issue-142029.rUpcmt.rst diff --git a/Lib/test/test_import/__init__.py b/Lib/test/test_import/__init__.py index c5cabc6477c8..59c6dc4587c9 100644 --- a/Lib/test/test_import/__init__.py +++ b/Lib/test/test_import/__init__.py @@ -1255,15 +1255,23 @@ os.does_not_exist def test_create_builtin(self): class Spec: - name = None + pass spec = Spec() + spec.name = "sys" + self.assertIs(_imp.create_builtin(spec), sys) + + spec.name = None with self.assertRaisesRegex(TypeError, 'name must be string, not NoneType'): _imp.create_builtin(spec) - spec.name = "" + # gh-142029 + spec.name = "nonexistent_lib" + with self.assertRaises(ModuleNotFoundError): + _imp.create_builtin(spec) # gh-142029 + spec.name = "" with self.assertRaisesRegex(ValueError, 'name must not be empty'): _imp.create_builtin(spec) diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-11-29-08-51-56.gh-issue-142029.rUpcmt.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-11-29-08-51-56.gh-issue-142029.rUpcmt.rst new file mode 100644 index 000000000000..017761adb125 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2025-11-29-08-51-56.gh-issue-142029.rUpcmt.rst @@ -0,0 +1,2 @@ +Raise :exc:`ModuleNotFoundError` instead of crashing when a nonexistent module +is used as a name in ``_imp.create_builtin()``. diff --git a/Python/import.c b/Python/import.c index f4decf6e5cd2..db433dbc971d 100644 --- a/Python/import.c +++ b/Python/import.c @@ -2383,12 +2383,12 @@ is_builtin(PyObject *name) return 0; } -static PyModInitFunction -lookup_inittab_initfunc(const struct _Py_ext_module_loader_info* info) +static struct _inittab* +lookup_inittab_entry(const struct _Py_ext_module_loader_info* info) { for (struct _inittab *p = INITTAB; p->name != NULL; p++) { if (_PyUnicode_EqualToASCIIString(info->name, p->name)) { - return (PyModInitFunction)p->initfunc; + return p; } } // not found @@ -2430,16 +2430,28 @@ create_builtin( _extensions_cache_delete(info.path, info.name); } - PyModInitFunction p0 = initfunc; - if (p0 == NULL) { - p0 = lookup_inittab_initfunc(&info); - if (p0 == NULL) { - /* Cannot re-init internal module ("sys" or "builtins") */ - assert(is_core_module(tstate->interp, info.name, info.path)); - mod = import_add_module(tstate, info.name); + PyModInitFunction p0 = NULL; + if (initfunc == NULL) { + struct _inittab *entry = lookup_inittab_entry(&info); + if (entry == NULL) { + mod = NULL; + _PyErr_SetModuleNotFoundError(name); goto finally; } + + p0 = (PyModInitFunction)entry->initfunc; } + else { + p0 = initfunc; + } + + if (p0 == NULL) { + /* Cannot re-init internal module ("sys" or "builtins") */ + assert(is_core_module(tstate->interp, info.name, info.path)); + mod = import_add_module(tstate, info.name); + goto finally; + } + #ifdef Py_GIL_DISABLED // This call (and the corresponding call to _PyImport_CheckGILForModule()) -- 2.47.3