gh-105340: include hidden fast-locals in locals() (#105715)

* gh-105340: include hidden fast-locals in locals()
This commit is contained in:
Carl Meyer 2023-07-05 17:05:02 -06:00 committed by GitHub
parent 838406b4fc
commit 104d7b760f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 160 additions and 44 deletions

View file

@ -908,7 +908,7 @@ builtin_eval_impl(PyObject *module, PyObject *source, PyObject *globals,
PyObject *locals)
/*[clinic end generated code: output=0a0824aa70093116 input=11ee718a8640e527]*/
{
PyObject *result, *source_copy;
PyObject *result = NULL, *source_copy;
const char *str;
if (locals != Py_None && !PyMapping_Check(locals)) {
@ -924,19 +924,25 @@ builtin_eval_impl(PyObject *module, PyObject *source, PyObject *globals,
if (globals == Py_None) {
globals = PyEval_GetGlobals();
if (locals == Py_None) {
locals = PyEval_GetLocals();
locals = _PyEval_GetFrameLocals();
if (locals == NULL)
return NULL;
}
else {
Py_INCREF(locals);
}
}
else if (locals == Py_None)
locals = globals;
locals = Py_NewRef(globals);
else {
Py_INCREF(locals);
}
if (globals == NULL || locals == NULL) {
PyErr_SetString(PyExc_TypeError,
"eval must be given globals and locals "
"when called without a frame");
return NULL;
goto error;
}
int r = PyDict_Contains(globals, &_Py_ID(__builtins__));
@ -944,34 +950,38 @@ builtin_eval_impl(PyObject *module, PyObject *source, PyObject *globals,
r = PyDict_SetItem(globals, &_Py_ID(__builtins__), PyEval_GetBuiltins());
}
if (r < 0) {
return NULL;
goto error;
}
if (PyCode_Check(source)) {
if (PySys_Audit("exec", "O", source) < 0) {
return NULL;
goto error;
}
if (PyCode_GetNumFree((PyCodeObject *)source) > 0) {
PyErr_SetString(PyExc_TypeError,
"code object passed to eval() may not contain free variables");
return NULL;
goto error;
}
return PyEval_EvalCode(source, globals, locals);
result = PyEval_EvalCode(source, globals, locals);
}
else {
PyCompilerFlags cf = _PyCompilerFlags_INIT;
cf.cf_flags = PyCF_SOURCE_IS_UTF8;
str = _Py_SourceAsString(source, "eval", "string, bytes or code", &cf, &source_copy);
if (str == NULL)
goto error;
while (*str == ' ' || *str == '\t')
str++;
(void)PyEval_MergeCompilerFlags(&cf);
result = PyRun_StringFlags(str, Py_eval_input, globals, locals, &cf);
Py_XDECREF(source_copy);
}
PyCompilerFlags cf = _PyCompilerFlags_INIT;
cf.cf_flags = PyCF_SOURCE_IS_UTF8;
str = _Py_SourceAsString(source, "eval", "string, bytes or code", &cf, &source_copy);
if (str == NULL)
return NULL;
while (*str == ' ' || *str == '\t')
str++;
(void)PyEval_MergeCompilerFlags(&cf);
result = PyRun_StringFlags(str, Py_eval_input, globals, locals, &cf);
Py_XDECREF(source_copy);
error:
Py_XDECREF(locals);
return result;
}
@ -1006,36 +1016,43 @@ builtin_exec_impl(PyObject *module, PyObject *source, PyObject *globals,
if (globals == Py_None) {
globals = PyEval_GetGlobals();
if (locals == Py_None) {
locals = PyEval_GetLocals();
locals = _PyEval_GetFrameLocals();
if (locals == NULL)
return NULL;
}
else {
Py_INCREF(locals);
}
if (!globals || !locals) {
PyErr_SetString(PyExc_SystemError,
"globals and locals cannot be NULL");
return NULL;
}
}
else if (locals == Py_None)
locals = globals;
else if (locals == Py_None) {
locals = Py_NewRef(globals);
}
else {
Py_INCREF(locals);
}
if (!PyDict_Check(globals)) {
PyErr_Format(PyExc_TypeError, "exec() globals must be a dict, not %.100s",
Py_TYPE(globals)->tp_name);
return NULL;
goto error;
}
if (!PyMapping_Check(locals)) {
PyErr_Format(PyExc_TypeError,
"locals must be a mapping or None, not %.100s",
Py_TYPE(locals)->tp_name);
return NULL;
goto error;
}
int r = PyDict_Contains(globals, &_Py_ID(__builtins__));
if (r == 0) {
r = PyDict_SetItem(globals, &_Py_ID(__builtins__), PyEval_GetBuiltins());
}
if (r < 0) {
return NULL;
goto error;
}
if (closure == Py_None) {
@ -1048,7 +1065,7 @@ builtin_exec_impl(PyObject *module, PyObject *source, PyObject *globals,
if (closure) {
PyErr_SetString(PyExc_TypeError,
"cannot use a closure with this code object");
return NULL;
goto error;
}
} else {
int closure_is_ok =
@ -1068,12 +1085,12 @@ builtin_exec_impl(PyObject *module, PyObject *source, PyObject *globals,
PyErr_Format(PyExc_TypeError,
"code object requires a closure of exactly length %zd",
num_free);
return NULL;
goto error;
}
}
if (PySys_Audit("exec", "O", source) < 0) {
return NULL;
goto error;
}
if (!closure) {
@ -1100,7 +1117,7 @@ builtin_exec_impl(PyObject *module, PyObject *source, PyObject *globals,
"string, bytes or code", &cf,
&source_copy);
if (str == NULL)
return NULL;
goto error;
if (PyEval_MergeCompilerFlags(&cf))
v = PyRun_StringFlags(str, Py_file_input, globals,
locals, &cf);
@ -1109,9 +1126,14 @@ builtin_exec_impl(PyObject *module, PyObject *source, PyObject *globals,
Py_XDECREF(source_copy);
}
if (v == NULL)
return NULL;
goto error;
Py_DECREF(locals);
Py_DECREF(v);
Py_RETURN_NONE;
error:
Py_XDECREF(locals);
return NULL;
}
@ -1721,10 +1743,7 @@ static PyObject *
builtin_locals_impl(PyObject *module)
/*[clinic end generated code: output=b46c94015ce11448 input=7874018d478d5c4b]*/
{
PyObject *d;
d = PyEval_GetLocals();
return Py_XNewRef(d);
return _PyEval_GetFrameLocals();
}
@ -2442,7 +2461,7 @@ builtin_vars_impl(PyObject *module, PyObject *object)
PyObject *d;
if (object == NULL) {
d = Py_XNewRef(PyEval_GetLocals());
d = _PyEval_GetFrameLocals();
}
else {
if (_PyObject_LookupAttr(object, &_Py_ID(__dict__), &d) == 0) {

View file

@ -2261,6 +2261,19 @@ PyEval_GetLocals(void)
return locals;
}
PyObject *
_PyEval_GetFrameLocals(void)
{
PyThreadState *tstate = _PyThreadState_GET();
_PyInterpreterFrame *current_frame = _PyThreadState_GetFrame(tstate);
if (current_frame == NULL) {
_PyErr_SetString(tstate, PyExc_SystemError, "frame does not exist");
return NULL;
}
return _PyFrame_GetLocals(current_frame, 1);
}
PyObject *
PyEval_GetGlobals(void)
{