changeset 643:e5363d3c22d3 experimental-sandboxed

some more work on the sandbox
author aronacher
date Wed, 26 Sep 2007 14:51:45 +0000
parents 1cf5fdfe7214
children e60298f5b17b
files genshi/template/eval.py genshi/template/loader.py genshi/util.py
diffstat 3 files changed, 18 insertions(+), 20 deletions(-) [+]
line wrap: on
line diff
--- a/genshi/template/eval.py
+++ b/genshi/template/eval.py
@@ -28,7 +28,7 @@
 
 from genshi.core import Markup
 from genshi.template.base import TemplateRuntimeError
-from genshi.util import flatten
+from genshi.util import flatten, safe_range
 
 __all__ = ['Code', 'Expression', 'Suite', 'LenientLookup', 'StrictLookup',
            'Undefined', 'UndefinedError']
@@ -489,13 +489,14 @@
 # underscores are valid we have to add __import__ here.
 UNSAFE_NAMES = ['file', 'open', 'eval', 'locals', 'globals', 'vars',
                 'help', 'quit', 'exit', 'input', 'raw_input', 'setattr',
-                'delattr', 'reload', 'compile', 'range', 'type']
+                'delattr', 'reload', 'compile', 'type']
 
 # XXX: provide a secure range function
 SECURE_BUILTINS = BUILTINS.copy()
 for _unsafe_name in UNSAFE_NAMES:
     del SECURE_BUILTINS[_unsafe_name]
 del _unsafe_name
+SECURE_BUILTINS['range'] = safe_range
 
 CONSTANTS = frozenset(['False', 'True', 'None', 'NotImplemented', 'Ellipsis'])
 
@@ -831,22 +832,6 @@
             node = ast.CallFunc(ast.Name('_lookup_name'), func_args)
         return node
 
-    def visitGetattr(self, node):
-        if self.secure:
-            return ast.CallFunc(ast.Name('_lookup_attr'), [
-                ast.Name('data'), self.visit(node.expr),
-                ast.Const(node.attrname)
-            ])
-        return ASTTransformer.visitGetattr(self, node)
-
-    def visitSubscript(self, node):
-        if self.secure:
-            return ast.CallFunc(ast.Name('_lookup_item'), [
-                ast.Name('data'), self.visit(node.expr),
-                ast.Tuple([self.visit(sub) for sub in node.subs])
-            ])
-        return ASTTransformer.visitSubscript(self, node)
-
 
 class ExpressionASTTransformer(TemplateASTTransformer):
     """Concrete AST transformer that implements the AST transformations needed
--- a/genshi/template/loader.py
+++ b/genshi/template/loader.py
@@ -77,7 +77,8 @@
     """
     def __init__(self, search_path=None, auto_reload=False,
                  default_encoding=None, max_cache_size=25, default_class=None,
-                 variable_lookup='strict', allow_exec=True, callback=None):
+                 variable_lookup='strict', allow_exec=True,
+                 secure=False, callback=None):
         """Create the template laoder.
         
         :param search_path: a list of absolute path names that should be
@@ -95,6 +96,7 @@
                                 (the default), "lenient", or a custom lookup
                                 class
         :param allow_exec: whether to allow Python code blocks in templates
+        :param secure: use secure template evaluation
         :param callback: (optional) a callback function that is invoked after a
                          template was initialized by this loader; the function
                          is passed the template object as only argument. This
@@ -120,6 +122,7 @@
         self.default_class = default_class or MarkupTemplate
         self.variable_lookup = variable_lookup
         self.allow_exec = allow_exec
+        self.secure = secure
         if callback is not None and not callable(callback):
             raise TypeError('The "callback" parameter needs to be callable')
         self.callback = callback
@@ -213,7 +216,8 @@
                         tmpl = cls(fileobj, basedir=dirname, filename=filename,
                                    loader=self, encoding=encoding,
                                    lookup=self.variable_lookup,
-                                   allow_exec=self.allow_exec)
+                                   allow_exec=self.allow_exec,
+                                   secure=self.secure)
                         if self.callback:
                             self.callback(tmpl)
                         self._cache[filename] = tmpl
--- a/genshi/util.py
+++ b/genshi/util.py
@@ -243,3 +243,12 @@
     :return: the text with tags removed
     """
     return _STRIPTAGS_RE.sub('', text)
+
+SAFE_RANGE_MAX = 10000
+def safe_range(*args):
+    """Save version of a normal range."""
+    rng = xrange(*args)
+    if len(rng) > SAFE_RANGE_MAX:
+        raise ValueError('cannot generate ranges with more than %d items.' %
+                         SAFE_RANGE_MAX)
+    return list(rng)
Copyright (C) 2012-2017 Edgewall Software