zopefoundation / RestrictedPython

A restricted execution environment for Python to run untrusted code.
http://restrictedpython.readthedocs.io/
Other
456 stars 38 forks source link

Local variables are not available from lambda #286

Closed KuzmichevaKsenia closed 2 weeks ago

KuzmichevaKsenia commented 3 weeks ago

Problem:

Local variables are not available from the body of the lambda function

What I did:

>>> from RestrictedPython import compile_restricted
>>> from RestrictedPython import safe_globals
>>>
>>> source_code = """
... STEP = 1
... increment = lambda x: x + STEP
... result = increment(1)
... """
>>>
>>> loc = {}
>>> byte_code = compile_restricted(source_code, '<inline>', 'exec')
>>> exec(byte_code, safe_globals, loc)

What I expect to happen:

>>> loc['result']
2

What actually happened:

Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "<inline>", line 4, in <module>
  File "<inline>", line 3, in <lambda>
NameError: name 'STEP' is not defined

What version of Python:

Python 3.8.10 RestrictedPython 7.2

d-maurer commented 3 weeks ago

Ksenia Kuzmicheva wrote at 2024-8-19 09:59 -0700:

Problem:

Local variables are not available from the body of the lambda function

What I did:

>>> from RestrictedPython import compile_restricted
>>> from RestrictedPython import safe_globals
>>>
>>> source_code = """
... STEP = 1
... increment = lambda x: x + STEP
... result = increment(1)
... """
>>>
>>> loc = {}
>>> byte_code = compile_restricted(source_code, '<inline>', 'exec')
>>> exec(byte_code, safe_globals, loc)

What I expect to happen:

>>> loc['result']
2

This is normal Python behavior (not limited to RestrictedPython) as demonstrated by the following transscript:

>>> s = """\
... STEP = 1
... increment = lambda x: x + STEP
... r = increment(1)
... """
>>>
>>> c = compile(s, "<inline>", "exec")
>>> glbs = {}
>>> lcls = {}
>>> exec(c, glbs, lcls)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<inline>", line 3, in <module>
  File "<inline>", line 2, in <lambda>
NameError: name 'STEP' is not defined

You can work around (in your special case) by not passing the local parameter to exec (thus using the same dict for locals and globals); you likely should pass a copy of safe_globals in this case as globals.

KuzmichevaKsenia commented 2 weeks ago

Got it. Thanks a lot for your reply!