https://github.com/python/cpython/commit/8fe5897853b1f5d8b7a1dc9fc2b72c6244a74983
commit: 8fe5897853b1f5d8b7a1dc9fc2b72c6244a74983
branch: 3.15
author: Miss Islington (bot) <[email protected]>
committer: pablogsal <[email protected]>
date: 2026-06-17T18:40:33Z
summary:

[3.15] gh-151510: Fix __lazy_import__ without frame (GH-151511) (#151610)

gh-151510: Fix __lazy_import__ without frame (GH-151511)
(cherry picked from commit eff805b7a7a9678639bbcebe804864406cc4eab2)

Co-authored-by: AN Long <[email protected]>

files:
A 
Misc/NEWS.d/next/Core_and_Builtins/2026-06-16-00-45-42.gh-issue-151510.HJ-kGn.rst
M Lib/test/test_lazy_import/__init__.py
M Modules/_testcapi/import.c
M Python/bltinmodule.c

diff --git a/Lib/test/test_lazy_import/__init__.py 
b/Lib/test/test_lazy_import/__init__.py
index c99c22491028d33..b531a4227bc9a88 100644
--- a/Lib/test/test_lazy_import/__init__.py
+++ b/Lib/test/test_lazy_import/__init__.py
@@ -1957,6 +1957,17 @@ def filter(*args):
     def test_set_bad_filter(self):
         self.assertRaises(ValueError, _testcapi.PyImport_SetLazyImportsFilter, 
42)
 
+    def test_dunder_lazy_import_without_frame(self):
+        # gh-151510: __lazy_import__() called with no globals and no running
+        # Python frame must raise TypeError instead of crashing.
+        with self.assertRaisesRegex(
+            TypeError,
+            r"__lazy_import__\(\) missing globals when called without a frame",
+        ):
+            _testcapi.lazy_import_without_frame(
+                "test.test_lazy_import.data.basic2"
+            )
+
 
 if __name__ == '__main__':
     unittest.main()
diff --git 
a/Misc/NEWS.d/next/Core_and_Builtins/2026-06-16-00-45-42.gh-issue-151510.HJ-kGn.rst
 
b/Misc/NEWS.d/next/Core_and_Builtins/2026-06-16-00-45-42.gh-issue-151510.HJ-kGn.rst
new file mode 100644
index 000000000000000..cfa5ee8d3839c1b
--- /dev/null
+++ 
b/Misc/NEWS.d/next/Core_and_Builtins/2026-06-16-00-45-42.gh-issue-151510.HJ-kGn.rst
@@ -0,0 +1,2 @@
+Fix a crash in :func:`!__lazy_import__` when called without an explicit
+``globals`` argument and without a current Python frame.
diff --git a/Modules/_testcapi/import.c b/Modules/_testcapi/import.c
index 384a8f52da4b984..11d0e6acaebe1f2 100644
--- a/Modules/_testcapi/import.c
+++ b/Modules/_testcapi/import.c
@@ -1,6 +1,27 @@
 #include "parts.h"
 #include "util.h"
 
+static PyObject *
+pyimport_lazyimportwithoutframe(PyObject *self, PyObject *name)
+{
+    PyObject *lazy_import = PyImport_ImportModuleAttrString("builtins",
+                                                            "__lazy_import__");
+    if (lazy_import == NULL) {
+        return NULL;
+    }
+
+    // Simulate being called with no running Python frame (e.g. from a freshly
+    // attached C thread), so that PyEval_GetGlobals() returns NULL.
+    PyThreadState *tstate = PyThreadState_Get();
+    struct _PyInterpreterFrame *saved = tstate->current_frame;
+    tstate->current_frame = NULL;
+    PyObject *res = PyObject_CallOneArg(lazy_import, name);
+    tstate->current_frame = saved;
+
+    Py_DECREF(lazy_import);
+    return res;
+}
+
 // Test PyImport_ImportModuleAttr()
 static PyObject *
 pyimport_importmoduleattr(PyObject *self, PyObject *args)
@@ -95,6 +116,7 @@ static PyMethodDef test_methods[] = {
     {"PyImport_GetLazyImportsMode", pyimport_getlazyimportsmode, METH_NOARGS},
     {"PyImport_SetLazyImportsFilter", pyimport_setlazyimportsfilter, 
METH_VARARGS},
     {"PyImport_GetLazyImportsFilter", pyimport_getlazyimportsfilter, 
METH_NOARGS},
+    {"lazy_import_without_frame", pyimport_lazyimportwithoutframe, METH_O},
     {NULL},
 };
 
diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c
index d5129bf6a5a6bc0..fa64255be00e75d 100644
--- a/Python/bltinmodule.c
+++ b/Python/bltinmodule.c
@@ -313,6 +313,12 @@ builtin___lazy_import___impl(PyObject *module, PyObject 
*name,
     PyThreadState *tstate = PyThreadState_GET();
     if (globals == NULL) {
         globals = PyEval_GetGlobals();
+        if (globals == NULL) {
+            PyErr_SetString(PyExc_TypeError,
+                            "__lazy_import__() missing globals "
+                            "when called without a frame");
+            return NULL;
+        }
     }
     if (locals == NULL) {
         locals = globals;

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]

Reply via email to