bpo-42990: Functions inherit current builtins#24564
bpo-42990: Functions inherit current builtins#24564vstinner merged 1 commit intopython:masterfrom vstinner:frame_new
Conversation
|
@markshannon: Does it sounds like a reasonable default behavior according to you? If someone wants to run a function in a builtins namespace different than the current builtins, it should be set explicitly in Once this PR will be merged, I plan to write a 3rd PR to add an optional builtins keyword-only parameter to the function constructor (FunctionType). |
|
This would allow code to access the builtins by creating a new function, side stepping any sand boxing in |
I added an unit test on the By the way, Python doesn't support sandboxes. There are many ways to access builtins. It has been proved by a very long list of "exploits" on the various Python sandbox attempts in the past. |
|
I had assumed that Would you mind putting the relevant changes in one PR and refactor in another? Also, do we really need yet another |
|
Without this PR, func_builtins2.py of https://bugs.python.org/issue43228 currently fails on master: "NameError: name 'len' is not defined". With this PR, func_builtins2.py works as expected (no exception). |
To be honest, I also "re-discovered" that exec() has this special behavior.
Right, sorry. I created PR #24566. I will merge it, and then rebase this one on top of it. |
The rationale for passing explicitly tstate is that getting the current Python Thread State may become slower when https://bugs.python.org/issue40522 will be fixed (to run multiple interpreters in parallel). I also expect that the compiler will be able to emit faster machine code, especially when using LTO, if tstate is passed explicitly. For example, I expect _PyErr_Occurred() to be inlined. |
|
I rebased my PR to restrict this change to the FunctionType constructor change. I merged the refactoring changes in a separated PR. |
|
I completed the documentation to clarify that this change makes types.FunctionType constructor more consistent with other Python functions like eval() and exec(). |
|
@gvanrossum @pablogsal: Does this behavior change sound reasonable to you? |
Misc/NEWS.d/next/Core and Builtins/2021-02-18-15-12-30.bpo-42990.toAqBH.rst
Outdated
Show resolved
Hide resolved
Misc/NEWS.d/next/Core and Builtins/2021-02-18-15-12-30.bpo-42990.toAqBH.rst
Outdated
Show resolved
Hide resolved
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().
|
@gvanrossum: Thanks for the review, I merged my PR. |
bpo-42990: Functions inherit current builtins (pythonGH-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 code doesn't like to run without `__builtins__`, so adding them if missing seems to be a good idea. Also that's what CPython >3.10 does. See python/cpython#24564 Resolves PyO3#3370
Python code doesn't like to run without `__builtins__`, so adding them if missing seems to be a good idea. Also that's what CPython >3.10 does. See python/cpython#24564 Resolves PyO3#3370
Python code doesn't like to run without `__builtins__`, so adding them if missing seems to be a good idea. Also that's what CPython >3.10 does. See python/cpython#24564 Resolves PyO3#3370
Python code doesn't like to run without `__builtins__`, so adding them if missing seems to be a good idea. Also that's what CPython >3.10 does. See python/cpython#24564 Resolves PyO3#3370
Python code doesn't like to run without `__builtins__`, so adding them if missing seems to be a good idea. Also that's what CPython >3.10 does. See python/cpython#24564 Resolves PyO3#3370
The types.FunctionType constructor now inherits the current builtins
if the globals parameter is used and the globals dictionary has no
"builtins" key, rather than rather than using {"None": None} as
builtins: same behavior than 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.
builtins cannot be found in globals.
https://bugs.python.org/issue42990