gh-151510: Fix __lazy_import__ without frame (#151511)

This commit is contained in:
AN Long
2026-06-18 03:09:51 +09:00
committed by GitHub
parent 16185e9fe2
commit eff805b7a7
4 changed files with 41 additions and 0 deletions
+11
View File
@@ -1949,6 +1949,17 @@ class LazyCApiTests(LazyImportTestCase):
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()
@@ -0,0 +1,2 @@
Fix a crash in :func:`!__lazy_import__` when called without an explicit
``globals`` argument and without a current Python frame.
+22
View File
@@ -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},
};
+6
View File
@@ -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;