diff --git a/Lib/test/test_import/__init__.py b/Lib/test/test_import/__init__.py index c905c0da0a1232..697b9a9924b255 100644 --- a/Lib/test/test_import/__init__.py +++ b/Lib/test/test_import/__init__.py @@ -364,6 +364,15 @@ def test_import_raises_ModuleNotFoundError(self): with self.assertRaises(ModuleNotFoundError): import something_that_should_not_exist_anywhere + def test_import_null_byte_in_name_raises_ModuleNotFoundError(self): + # gh-150633: module names containing null bytes should not + # lead to duplicates in sys.modules + before = set(sys.modules.keys()) + with self.assertRaises(ModuleNotFoundError): + __import__('codecs\x00junk') + + self.assertEqual(set(sys.modules.keys()), before) + def test_from_import_missing_module_raises_ModuleNotFoundError(self): with self.assertRaises(ModuleNotFoundError): from something_that_should_not_exist_anywhere import blah diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-05-30-20-19-35.gh-issue-150633.XkNul0.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-05-30-20-19-35.gh-issue-150633.XkNul0.rst new file mode 100644 index 00000000000000..d1788f3e9b9f7d --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-05-30-20-19-35.gh-issue-150633.XkNul0.rst @@ -0,0 +1,3 @@ +Fix :func:`__import__` accepting module names with embedded null bytes, which +caused the frozen importer to bypass the :data:`sys.modules` cache and create +duplicate module objects. diff --git a/Python/import.c b/Python/import.c index 2a8f7bddb98986..9ef122e7d8b7a8 100644 --- a/Python/import.c +++ b/Python/import.c @@ -3174,7 +3174,7 @@ find_frozen(PyObject *nameobj, struct frozen_info *info) if (nameobj == NULL || nameobj == Py_None) { return FROZEN_BAD_NAME; } - const char *name = PyUnicode_AsUTF8(nameobj); + const char *name = _PyUnicode_AsUTF8NoNUL(nameobj); if (name == NULL) { // Note that this function previously used // _PyUnicode_EqualToASCIIString(). We clear the error here