Commit ceef435d authored by Jim Fulton's avatar Jim Fulton

Added protection against the (small) risk that someone could mitate an

object through an augmented assignment (aka inplace) operator.

Also added handling for generator expressions.
parent 912a5266
......@@ -22,7 +22,9 @@ Zope Changes
- Collector #1233: port ZOPE_CONFIG patch from Zope 2.7 to Zope 2.8
After Zope 2.8.3
Zope 2.8.4
Bugs Fixed
......@@ -33,6 +35,13 @@ Zope Changes
- Collector #1926: fixed a typo in _doAddUser when password
encryption is enabled.
- If a content object implemented any in-place numeric operators,
untrusted code could call them, thus modifying the content.
- If Python 2.4 is used, despite the fact that Python 2.4 is
unsupported, untrusted code could use generator expressions to
gain access to container items.
Zope 2.8.3 (2005/10/18)
Other
......
......@@ -47,6 +47,7 @@ _getitem_name = ast.Name("_getitem_")
_getiter_name = ast.Name("_getiter_")
_print_target_name = ast.Name("_print")
_write_name = ast.Name("_write_")
_inplacevar_name = ast.Name("_inplacevar_")
# Constants.
_None_const = ast.Const(None)
......@@ -239,9 +240,9 @@ class RestrictionMutator:
# for x in expr:
# to
# for x in _getiter(expr):
# # Note that visitListCompFor is the same thing.
#
# Note that visitListCompFor is the same thing. Exactly the same
# transformation is needed to convert
# Also for list comprehensions:
# [... for x in expr ...]
# to
# [... for x in _getiter(expr) ...]
......@@ -251,6 +252,15 @@ class RestrictionMutator:
visitListCompFor = visitFor
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
def visitGetattr(self, node, walker):
"""Converts attribute access to a function call.
......@@ -365,8 +375,23 @@ class RestrictionMutator:
This could be a problem if untrusted code got access to a
mutable database object that supports augmented assignment.
"""
node.node.in_aug_assign = True
return walker.defaultVisitNode(node)
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)
def visitImport(self, node, walker):
"""Checks names imported using checkName()."""
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment