Spaces:
Sleeping
Sleeping
Fixing a bug
Browse files
restrictedpython_code_eval.py
CHANGED
|
@@ -155,6 +155,54 @@ class AllowAugmentedAssignAndUnderscoreVariableNamesRestrictingTransformer(Allow
|
|
| 155 |
def __init__(self, *args, **kwargs):
|
| 156 |
super().__init__(*args, **kwargs)
|
| 157 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 158 |
def check_name(self, node, name, allow_magic_methods=False):
|
| 159 |
if name is None:
|
| 160 |
return
|
|
|
|
| 155 |
def __init__(self, *args, **kwargs):
|
| 156 |
super().__init__(*args, **kwargs)
|
| 157 |
|
| 158 |
+
def visit_Attribute(self, node):
|
| 159 |
+
"""Checks and mutates attribute access/assignment.
|
| 160 |
+
|
| 161 |
+
'a.b' becomes '_getattr_(a, "b")'
|
| 162 |
+
'a.b = c' becomes '_write_(a).b = c'
|
| 163 |
+
'del a.b' becomes 'del _write_(a).b'
|
| 164 |
+
|
| 165 |
+
The _write_ function should return a security proxy.
|
| 166 |
+
"""
|
| 167 |
+
# Overriding here to allow select underscore names
|
| 168 |
+
if node.attr.startswith('_') and node.attr != '_' and node.attr not in ALLOWED_UNDERSCORE_NAMES:
|
| 169 |
+
self.error(
|
| 170 |
+
node,
|
| 171 |
+
'"{name}" is an invalid attribute name because it starts '
|
| 172 |
+
'with "_".'.format(name=node.attr))
|
| 173 |
+
|
| 174 |
+
if node.attr.endswith('__roles__'):
|
| 175 |
+
self.error(
|
| 176 |
+
node,
|
| 177 |
+
'"{name}" is an invalid attribute name because it ends '
|
| 178 |
+
'with "__roles__".'.format(name=node.attr))
|
| 179 |
+
|
| 180 |
+
if isinstance(node.ctx, ast.Load):
|
| 181 |
+
node = self.node_contents_visit(node)
|
| 182 |
+
new_node = ast.Call(
|
| 183 |
+
func=ast.Name('_getattr_', ast.Load()),
|
| 184 |
+
args=[node.value, ast.Str(node.attr)],
|
| 185 |
+
keywords=[])
|
| 186 |
+
|
| 187 |
+
copy_locations(new_node, node)
|
| 188 |
+
return new_node
|
| 189 |
+
|
| 190 |
+
elif isinstance(node.ctx, (ast.Store, ast.Del)):
|
| 191 |
+
node = self.node_contents_visit(node)
|
| 192 |
+
new_value = ast.Call(
|
| 193 |
+
func=ast.Name('_write_', ast.Load()),
|
| 194 |
+
args=[node.value],
|
| 195 |
+
keywords=[])
|
| 196 |
+
|
| 197 |
+
copy_locations(new_value, node.value)
|
| 198 |
+
node.value = new_value
|
| 199 |
+
return node
|
| 200 |
+
|
| 201 |
+
else: # pragma: no cover
|
| 202 |
+
# Impossible Case only ctx Load, Store and Del are defined in ast.
|
| 203 |
+
raise NotImplementedError(
|
| 204 |
+
f"Unknown ctx type: {type(node.ctx)}")
|
| 205 |
+
|
| 206 |
def check_name(self, node, name, allow_magic_methods=False):
|
| 207 |
if name is None:
|
| 208 |
return
|