示例#1
0
    def visitPrint(self, node, walker):
        """Checks and mutates a print statement.

        Adds a target to all print statements.  'print foo' becomes
        'print >> _print, foo', where _print is the default print
        target defined for this scope.

        Alternatively, if the untrusted code provides its own target,
        we have to check the 'write' method of the target.
        'print >> ob, foo' becomes
        'print >> (_getattr(ob, 'write') and ob), foo'.
        Otherwise, it would be possible to call the write method of
        templates and scripts; 'write' happens to be the name of the
        method that changes them.
        """
        node = walker.defaultVisitNode(node)
        self.funcinfo.print_used = True
        if node.dest is None:
            node.dest = _print_target_name
        else:
            # Pre-validate access to the "write" attribute.
            # "print >> ob, x" becomes
            # "print >> (_getattr(ob, 'write') and ob), x"
            node.dest = ast.And([
                ast.CallFunc(_getattr_name, [node.dest, _write_const]),
                node.dest
            ])
        return node
示例#2
0
    def visitAugAssign(self, node, walker):
        """Makes a note that augmented assignment is in use.

        Note that although augmented assignment of attributes and
        subscripts is disallowed, augmented assignment of names (such
        as 'n += 1') is allowed.

        This could be a problem if untrusted code got access to a
        mutable database object that supports augmented assignment.
        """
        if node.node.__class__.__name__ == 'Name':
            node = walker.defaultVisitNode(node)
            newnode = ast.Assign(
                [ast.AssName(node.node.name, OP_ASSIGN)],
                ast.CallFunc(_inplacevar_name, [
                    ast.Const(node.op),
                    ast.Name(node.node.name),
                    node.expr,
                ]),
            )
            newnode.lineno = node.lineno
            return newnode
        else:
            node.node.in_aug_assign = True
            return walker.defaultVisitNode(node)
示例#3
0
    def visitSubscript(self, node, walker):
        """Checks all kinds of subscripts.

        'foo[bar] += baz' is disallowed.
        'a = foo[bar, baz]' becomes 'a = _getitem(foo, (bar, baz))'.
        'a = foo[bar]' becomes 'a = _getitem(foo, bar)'.
        'a = foo[bar:baz]' becomes 'a = _getitem(foo, slice(bar, baz))'.
        'a = foo[:baz]' becomes 'a = _getitem(foo, slice(None, baz))'.
        'a = foo[bar:]' becomes 'a = _getitem(foo, slice(bar, None))'.
        'del foo[bar]' becomes 'del _write(foo)[bar]'.
        'foo[bar] = a' becomes '_write(foo)[bar] = a'.

        The _write function returns a security proxy.
        """
        node = walker.defaultVisitNode(node)
        if node.flags == OP_APPLY:
            # Set 'subs' to the node that represents the subscript or slice.
            if getattr(node, 'in_aug_assign', False):
                # We're in an augmented assignment
                # We might support this later...
                self.error(
                    node, 'Augmented assignment of '
                    'object items and slices is not allowed.')
            if hasattr(node, 'subs'):
                # Subscript.
                subs = node.subs
                if len(subs) > 1:
                    # example: ob[1,2]
                    subs = ast.Tuple(subs)
                else:
                    # example: ob[1]
                    subs = subs[0]
            else:
                # Slice.
                # example: obj[0:2]
                lower = node.lower
                if lower is None:
                    lower = _None_const
                upper = node.upper
                if upper is None:
                    upper = _None_const
                subs = ast.Sliceobj([lower, upper])
            return ast.CallFunc(_getitem_name, [node.expr, subs])
        elif node.flags in (OP_DELETE, OP_ASSIGN):
            # set or remove subscript or slice
            node.expr = ast.CallFunc(_write_name, [node.expr])
        return node
示例#4
0
 def visitGenExprFor(self, node, walker):
     # convert
     #   (... for x in expr ...)
     # to
     #   (... for x in _getiter(expr) ...)
     node = walker.defaultVisitNode(node)
     node.iter = ast.CallFunc(_getiter_name, [node.iter])
     return node
示例#5
0
    def visitAssAttr(self, node, walker):
        """Checks and mutates attribute assignment.

        'a.b = c' becomes '_write(a).b = c'.
        The _write function returns a security proxy.
        """
        self.checkAttrName(node)
        node = walker.defaultVisitNode(node)
        node.expr = ast.CallFunc(_write_name, [node.expr])
        return node
示例#6
0
 def visitFor(self, node, walker):
     # convert
     #   for x in expr:
     # to
     #   for x in _getiter(expr):
     #        # Note that visitListCompFor is the same thing.
     #
     # Also for list comprehensions:
     #   [... for x in expr ...]
     # to
     #   [... for x in _getiter(expr) ...]
     node = walker.defaultVisitNode(node)
     node.list = ast.CallFunc(_getiter_name, [node.list])
     return node
示例#7
0
    def visitGetattr(self, node, walker):
        """Converts attribute access to a function call.

        'foo.bar' becomes '_getattr(foo, "bar")'.

        Also prevents augmented assignment of attributes, which would
        be difficult to support correctly.
        """
        self.checkAttrName(node)
        node = walker.defaultVisitNode(node)
        if getattr(node, 'in_aug_assign', False):
            # We're in an augmented assignment
            # We might support this later...
            self.error(node, 'Augmented assignment of '
                       'attributes is not allowed.')
        return ast.CallFunc(_getattr_name,
                            [node.expr, ast.Const(node.attrname)])