From 46496f9d12582bf11f4911ad0f23315d6f277907 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Sat, 20 Feb 2021 15:17:18 +0100 Subject: bpo-42990: Functions inherit current builtins (GH-24564) The types.FunctionType constructor now inherits the current builtins if the globals dictionary has no "__builtins__" key, rather than using {"None": None} as builtins: same behavior as eval() and exec() functions. Defining a function with "def function(...): ..." in Python is not affected, globals cannot be overriden with this syntax: it also inherits the current builtins. PyFrame_New(), PyEval_EvalCode(), PyEval_EvalCodeEx(), PyFunction_New() and PyFunction_NewWithQualName() now inherits the current builtins namespace if the globals dictionary has no "__builtins__" key. * Add _PyEval_GetBuiltins() function. * _PyEval_BuiltinsFromGlobals() now uses _PyEval_GetBuiltins() if builtins cannot be found in globals. * Add tstate parameter to _PyEval_BuiltinsFromGlobals(). --- Python/ceval.c | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) (limited to 'Python/ceval.c') diff --git a/Python/ceval.c b/Python/ceval.c index 7ccb8fcf5a..e2b2d211fb 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -889,10 +889,11 @@ static int unpack_iterable(PyThreadState *, PyObject *, int, int, PyObject **); PyObject * PyEval_EvalCode(PyObject *co, PyObject *globals, PyObject *locals) { + PyThreadState *tstate = PyThreadState_GET(); if (locals == NULL) { locals = globals; } - PyObject *builtins = _PyEval_BuiltinsFromGlobals(globals); + PyObject *builtins = _PyEval_BuiltinsFromGlobals(tstate, globals); if (builtins == NULL) { return NULL; } @@ -906,10 +907,7 @@ PyEval_EvalCode(PyObject *co, PyObject *globals, PyObject *locals) .fc_kwdefaults = NULL, .fc_closure = NULL }; - PyThreadState *tstate = PyThreadState_GET(); - PyObject *res = _PyEval_Vector(tstate, &desc, locals, NULL, 0, NULL); - Py_DECREF(builtins); - return res; + return _PyEval_Vector(tstate, &desc, locals, NULL, 0, NULL); } @@ -4733,12 +4731,13 @@ PyEval_EvalCodeEx(PyObject *_co, PyObject *globals, PyObject *locals, PyObject *const *defs, int defcount, PyObject *kwdefs, PyObject *closure) { + PyThreadState *tstate = _PyThreadState_GET(); PyObject *res; PyObject *defaults = _PyTuple_FromArray(defs, defcount); if (defaults == NULL) { return NULL; } - PyObject *builtins = _PyEval_BuiltinsFromGlobals(globals); + PyObject *builtins = _PyEval_BuiltinsFromGlobals(tstate, globals); if (builtins == NULL) { Py_DECREF(defaults); return NULL; @@ -4797,7 +4796,6 @@ PyEval_EvalCodeEx(PyObject *_co, PyObject *globals, PyObject *locals, .fc_kwdefaults = kwdefs, .fc_closure = closure }; - PyThreadState *tstate = _PyThreadState_GET(); res = _PyEval_Vector(tstate, &constr, locals, allargs, argcount, kwnames); @@ -5315,15 +5313,21 @@ PyEval_GetFrame(void) return tstate->frame; } +PyObject * +_PyEval_GetBuiltins(PyThreadState *tstate) +{ + PyFrameObject *frame = tstate->frame; + if (frame != NULL) { + return frame->f_builtins; + } + return tstate->interp->builtins; +} + PyObject * PyEval_GetBuiltins(void) { PyThreadState *tstate = _PyThreadState_GET(); - PyFrameObject *current_frame = tstate->frame; - if (current_frame == NULL) - return tstate->interp->builtins; - else - return current_frame->f_builtins; + return _PyEval_GetBuiltins(tstate); } /* Convenience function to get a builtin from its name */ -- cgit v1.2.3