gh-135443: Sometimes Fall Back to __main__.__dict__ For Globals (gh-135491)

For several builtin functions, we now fall back to __main__.__dict__ for the globals
when there is no current frame and _PyInterpreterState_IsRunningMain() returns
true.  This allows those functions to be run with Interpreter.call().

The affected builtins:

* exec()
* eval()
* globals()
* locals()
* vars()
* dir()

We take a similar approach with "stateless" functions, which don't use any
global variables.
This commit is contained in:
Eric Snow 2025-06-16 17:34:19 -06:00 committed by GitHub
parent 68b7e1a667
commit a450a0ddec
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 394 additions and 68 deletions

View file

@ -3960,25 +3960,28 @@ PyImport_Import(PyObject *module_name)
}
/* Get the builtins from current globals */
globals = PyEval_GetGlobals();
globals = PyEval_GetGlobals(); // borrowed
if (globals != NULL) {
Py_INCREF(globals);
// XXX Use _PyEval_EnsureBuiltins()?
builtins = PyObject_GetItem(globals, &_Py_ID(__builtins__));
if (builtins == NULL) {
// XXX Fall back to interp->builtins or sys.modules['builtins']?
goto err;
}
}
else if (_PyErr_Occurred(tstate)) {
goto err;
}
else {
/* No globals -- use standard builtins, and fake globals */
builtins = PyImport_ImportModuleLevel("builtins",
NULL, NULL, NULL, 0);
if (builtins == NULL) {
globals = PyDict_New();
if (globals == NULL) {
goto err;
}
globals = Py_BuildValue("{OO}", &_Py_ID(__builtins__), builtins);
if (globals == NULL)
if (_PyEval_EnsureBuiltinsWithModule(tstate, globals, &builtins) < 0) {
goto err;
}
}
/* Get the __import__ function from the builtins */