From: Stan Ulbrych <89152624+StanFromIreland@users.noreply.github.com> Date: Sat, 21 Feb 2026 12:52:40 +0000 (+0000) Subject: gh-145058: Add input validation to `_PyImport_LazyImportModuleLevelObject` (#145068) X-Git-Tag: v3.15.0a7~194 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e1bd0cd37b1816092761e5ad5f2d0464c0e78fbb;p=thirdparty%2FPython%2Fcpython.git gh-145058: Add input validation to `_PyImport_LazyImportModuleLevelObject` (#145068) --- diff --git a/Lib/test/test_import/test_lazy_imports.py b/Lib/test/test_import/test_lazy_imports.py index a4c9c14ae2b5..dc185c070acc 100644 --- a/Lib/test/test_import/test_lazy_imports.py +++ b/Lib/test/test_import/test_lazy_imports.py @@ -393,6 +393,15 @@ class DunderLazyImportTests(unittest.TestCase): import test.test_import.data.lazy_imports.dunder_lazy_import_used self.assertIn("test.test_import.data.lazy_imports.basic2", sys.modules) + def test_dunder_lazy_import_invalid_arguments(self): + """__lazy_import__ should reject invalid arguments.""" + for invalid_name in (b"", 123, None): + with self.assertRaises(TypeError): + __lazy_import__(invalid_name) + + with self.assertRaises(ValueError): + __lazy_import__("sys", level=-1) + def test_dunder_lazy_import_builtins(self): """__lazy_import__ should use module's __builtins__ for __import__.""" from test.test_import.data.lazy_imports import dunder_lazy_import_builtins diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-02-21-09-47-45.gh-issue-145058.e-RBw-.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-02-21-09-47-45.gh-issue-145058.e-RBw-.rst new file mode 100644 index 000000000000..05eb296f96ec --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-02-21-09-47-45.gh-issue-145058.e-RBw-.rst @@ -0,0 +1,2 @@ +Fix a crash when :func:`!__lazy_import__` is passed a non-string argument, +by raising an :exc:`TypeError` instead. diff --git a/Python/import.c b/Python/import.c index c20c55727d2f..4c234a4a7043 100644 --- a/Python/import.c +++ b/Python/import.c @@ -4468,6 +4468,17 @@ _PyImport_LazyImportModuleLevelObject(PyThreadState *tstate, PyObject *globals, PyObject *locals, PyObject *fromlist, int level) { + assert(name != NULL); + if (!PyUnicode_Check(name)) { + _PyErr_Format(tstate, PyExc_TypeError, + "module name must be a string, got %T", name); + return NULL; + } + if (level < 0) { + _PyErr_SetString(tstate, PyExc_ValueError, "level must be >= 0"); + return NULL; + } + PyObject *abs_name = get_abs_name(tstate, name, globals, level); if (abs_name == NULL) { return NULL;