Skip to content

Commit f3f5795

Browse files
pablogsalDinoV
authored andcommitted
Fix recursive lazy imports and error path in bytecodes.c
1 parent f9880bf commit f3f5795

File tree

6 files changed

+18
-6
lines changed

6 files changed

+18
-6
lines changed

Include/internal/pycore_import.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ _PyImport_LazyImportModuleLevelObject(PyThreadState *tstate, PyObject *name, PyO
5757
#define IMPORTS_INIT \
5858
{ \
5959
DLOPENFLAGS_INIT \
60+
.lazy_import_resolution_depth = 0, \
6061
.find_and_load = { \
6162
.header = 1, \
6263
}, \

Include/internal/pycore_interp_structs.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,8 @@ struct _import_state {
316316
PyObject *lazy_import_func;
317317
int lazy_imports_mode;
318318
PyObject *lazy_imports_filter;
319+
/* Counter to prevent recursive lazy import creation */
320+
int lazy_import_resolution_depth;
319321
/* The global import lock. */
320322
_PyRecursiveMutex lock;
321323
/* diagnostic info in PyImport_ImportModuleLevelObject() */

Python/bytecodes.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1835,7 +1835,7 @@ dummy_func(
18351835
PyObject *res_o = PyStackRef_AsPyObjectBorrow(*res);
18361836
if (PyLazyImport_CheckExact(res_o)) {
18371837
PyObject *l_v = _PyImport_LoadLazyImportTstate(tstate, res_o);
1838-
if (PyDict_SetItem(GLOBALS(), name, l_v) < 0) {
1838+
if (l_v != NULL && PyDict_SetItem(GLOBALS(), name, l_v) < 0) {
18391839
JUMP_TO_LABEL(error);
18401840
}
18411841
res_o = l_v;

Python/executor_cases.c.h

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Python/generated_cases.c.h

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Python/import.c

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3738,6 +3738,10 @@ _PyImport_LoadLazyImportTstate(PyThreadState *tstate, PyObject *lazy_import)
37383738

37393739
PyObject *globals = PyEval_GetGlobals();
37403740

3741+
// Increment counter to prevent recursive lazy import creation
3742+
PyInterpreterState *interp = tstate->interp;
3743+
interp->imports.lazy_import_resolution_depth++;
3744+
37413745
if (full) {
37423746
obj = _PyEval_ImportNameWithImport(tstate,
37433747
lz->lz_import_func,
@@ -3749,6 +3753,7 @@ _PyImport_LoadLazyImportTstate(PyThreadState *tstate, PyObject *lazy_import)
37493753
} else {
37503754
PyObject *name = PyUnicode_Substring(lz->lz_from, 0, dot);
37513755
if (name == NULL) {
3756+
interp->imports.lazy_import_resolution_depth--;
37523757
goto error;
37533758
}
37543759
obj = _PyEval_ImportNameWithImport(tstate,
@@ -3761,6 +3766,9 @@ _PyImport_LoadLazyImportTstate(PyThreadState *tstate, PyObject *lazy_import)
37613766
Py_DECREF(name);
37623767
}
37633768

3769+
// Decrement counter
3770+
interp->imports.lazy_import_resolution_depth--;
3771+
37643772
if (obj == NULL) {
37653773
goto error;
37663774
}
@@ -3942,7 +3950,8 @@ PyImport_ImportModuleLevelObject(PyObject *name, PyObject *globals,
39423950
goto error;
39433951
}
39443952

3945-
if (globals != NULL &&
3953+
// Only check __lazy_modules__ if we're not already resolving a lazy import
3954+
if (interp->imports.lazy_import_resolution_depth == 0 && globals != NULL &&
39463955
PyMapping_GetOptionalItem(globals, &_Py_ID(__lazy_modules__), &lazy_modules) < 0) {
39473956
goto error;
39483957
}
@@ -3965,7 +3974,7 @@ PyImport_ImportModuleLevelObject(PyObject *name, PyObject *globals,
39653974
goto error;
39663975
}
39673976

3968-
if (lazy_modules != NULL) {
3977+
if (interp->imports.lazy_import_resolution_depth == 0 && lazy_modules != NULL) {
39693978
// Check and see if the module is opting in w/o syntax for backwards compatibility
39703979
// with older Python versions.
39713980
int contains = PySequence_Contains(lazy_modules, name);
@@ -3988,7 +3997,7 @@ PyImport_ImportModuleLevelObject(PyObject *name, PyObject *globals,
39883997
return NULL;
39893998
}
39903999

3991-
final_mod = _PyImport_LazyImportModuleLevelObject(tstate, name, import_func, globals,
4000+
final_mod = _PyImport_LazyImportModuleLevelObject(tstate, name, import_func, globals,
39924001
locals, fromlist, level);
39934002
Py_DECREF(import_func);
39944003
goto error;

0 commit comments

Comments
 (0)