mirror of
https://github.com/python/cpython.git
synced 2026-06-21 02:22:23 -04:00
gh-151510: Fix __lazy_import__ without frame (#151511)
This commit is contained in:
@@ -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.
|
||||
@@ -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},
|
||||
};
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user