diff options
Diffstat (limited to 'src/zope/pagetemplate')
-rw-r--r-- | src/zope/pagetemplate/engine.py | 27 | ||||
-rw-r--r-- | src/zope/pagetemplate/tests/test_engine.py | 30 |
2 files changed, 32 insertions, 25 deletions
diff --git a/src/zope/pagetemplate/engine.py b/src/zope/pagetemplate/engine.py index 662dbcd..9b61498 100644 --- a/src/zope/pagetemplate/engine.py +++ b/src/zope/pagetemplate/engine.py @@ -33,13 +33,17 @@ from zope.traversing.interfaces import TraversalError from zope import component -try: # pragma: no cover - # Until https://github.com/zopefoundation/zope.untrustedpython/issues/2 - # is fixed Python 3 does not support special handling for untrusted code: +try: + # The ``untrusted`` extra is needed to have zope.untrustedpython: from zope.untrustedpython import rcompile from zope.untrustedpython.builtins import SafeBuiltins + + def guarded_getitem(ob, index): + """getitem access which gets guarded in the next line.""" + return ob[index] + guarded_getitem = ProxyFactory(guarded_getitem) HAVE_UNTRUSTED = True -except ImportError: +except ImportError: # pragma: no cover HAVE_UNTRUSTED = False # PyPy doesn't support assigning to '__builtins__', even when using eval() @@ -128,6 +132,8 @@ class ZopePythonExpr(PythonExpr): def __call__(self, econtext): __traceback_info__ = self.text vars = self._bind_used_names(econtext, SafeBuiltins) + vars['_getattr_'] = SafeBuiltins.getattr + vars['_getitem_'] = guarded_getitem return eval(self._code, vars) def _compile(self, text, filename): @@ -363,14 +369,15 @@ class ZopeEngine(ZopeBaseEngine): wrapped in security proxies if the 'untrusted' extra is installed:: >>> r = context.evaluate('python: {12: object()}.values') - >>> str(type(r).__name__) in ( - ... ('_Proxy',) if HAVE_UNTRUSTED else - ... ('builtin_function_or_method', 'method', 'instancemethod')) + >>> str(type(r).__name__) if HAVE_UNTRUSTED else '_Proxy' + '_Proxy' + >>> ((str(type(r).__name__) in ('method', 'instancemethod')) + ... if not HAVE_UNTRUSTED else True) True - >>> r = context.evaluate('python: {12: object()}[12].__class__') - >>> str(type(r).__name__) == '_Proxy' or not HAVE_UNTRUSTED - True + >>> r = context.evaluate('python: {12: (1, 2, 3)}[12]') + >>> str(type(r).__name__) if HAVE_UNTRUSTED else '_Proxy' + '_Proxy' General path expressions provide objects that are wrapped in security proxies as well:: diff --git a/src/zope/pagetemplate/tests/test_engine.py b/src/zope/pagetemplate/tests/test_engine.py index 946cfba..714d4d2 100644 --- a/src/zope/pagetemplate/tests/test_engine.py +++ b/src/zope/pagetemplate/tests/test_engine.py @@ -51,11 +51,7 @@ class DummyEngine: return {} def getCompilerError(self): - # This is only here to get meaningful errors if RestrictedPython denies - # execution of some code. - def get_error(text): # pragma: no cover - raise RuntimeError(text) # pragma: no cover - return get_error # pragma: no cover + return SyntaxError # pragma: no cover class DummyContext: @@ -73,21 +69,25 @@ class ZopePythonExprTests(unittest.TestCase): expr = ZopePythonExpr('python', 'max(a,b)', DummyEngine()) self.assertEqual(expr(DummyContext(a=1, b=2)), 2) - def test_allowed_module_name(self): + def test_import_not_possible(self): from zope.pagetemplate.engine import ZopePythonExpr - expr = ZopePythonExpr('python', '__import__("sys").__name__', - DummyEngine()) - self.assertEqual(expr(DummyContext()), 'sys') + with self.assertRaises(SyntaxError) as err: + ZopePythonExpr('python', 'import sys', DummyEngine()) + if zope.pagetemplate.engine.HAVE_UNTRUSTED: + self.assertIn( + 'SyntaxError: invalid syntax at statement', str(err.exception)) + else: + self.assertEqual( + 'invalid syntax (<string>, line 1)', str(err.exception)) @unittest.skipUnless(zope.pagetemplate.engine.HAVE_UNTRUSTED, "Needs untrusted") - def test_forbidden_module_name(self): - from zope.security.interfaces import Forbidden - + def test___import___not_allowed(self): from zope.pagetemplate.engine import ZopePythonExpr - expr = ZopePythonExpr('python', '__import__("sys").exit', - DummyEngine()) - self.assertRaises(Forbidden, expr, DummyContext()) + with self.assertRaises(SyntaxError) as err: + ZopePythonExpr('python', '__import__("sys")', DummyEngine()) + self.assertIn( + '"__import__" is an invalid variable', str(err.exception)) @unittest.skipUnless(zope.pagetemplate.engine.HAVE_UNTRUSTED, "Needs untrusted") |