Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@ python:
- pypy-5.4
env:
- ENVIRON=py
- ENVIRON=isort
- ENVIRON=isort,flake8
matrix:
exclude:
- env: ENVIRON=isort
- env: ENVIRON=isort,flake8
include:
- python: "3.6"
env: ENVIRON=isort
env: ENVIRON=isort,flake8
install:
- pip install tox coveralls coverage
script:
Expand Down
5 changes: 5 additions & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,8 @@ force_single_line = True
lines_after_imports = 2
line_length = 200
not_skip = __init__.py

[flake8]
exclude = src/RestrictedPython/tests,
src/RestrictedPython/__init__.py,
src/RestrictedPython/SelectCompiler.py,
2 changes: 1 addition & 1 deletion src/RestrictedPython/Eval.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
"""Restricted Python Expressions."""

from RestrictedPython.RCompile import compile_restricted_eval
#from RestrictedPython.compile import compile_restricted_eval
from string import strip
from string import translate

Expand All @@ -29,6 +28,7 @@ def default_guarded_getitem(ob, index):
# No restrictions.
return ob[index]


PROFILE = 0


Expand Down
9 changes: 8 additions & 1 deletion src/RestrictedPython/Guards.py
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,8 @@ def __init__(self, ob):
def _full_write_guard():
# Nested scope abuse!
# safetype and Wrapper variables are used by guard()
safetype = {dict: True, list: True}.has_key if IS_PY2 else {dict: True, list: True}.keys
safetype = ({dict: True, list: True}.has_key if IS_PY2 else
{dict: True, list: True}.keys)
Wrapper = _write_wrapper()

def guard(ob):
Expand All @@ -240,16 +241,22 @@ def guard(ob):
# Hand the object to the Wrapper instance, then return the instance.
return Wrapper(ob)
return guard


full_write_guard = _full_write_guard()


def guarded_setattr(object, name, value):
setattr(full_write_guard(object), name, value)


safe_builtins['setattr'] = guarded_setattr


def guarded_delattr(object, name):
delattr(full_write_guard(object), name)


safe_builtins['delattr'] = guarded_delattr


Expand Down
6 changes: 6 additions & 0 deletions src/RestrictedPython/Limits.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,18 +33,24 @@ def _limited_range(iFirst, *args):
if iLen >= RANGELIMIT:
raise ValueError('range() too large')
return range(iStart, iEnd, iStep)


limited_builtins['range'] = _limited_range


def _limited_list(seq):
if isinstance(seq, str):
raise TypeError('cannot convert string to list')
return list(seq)


limited_builtins['list'] = _limited_list


def _limited_tuple(seq):
if isinstance(seq, str):
raise TypeError('cannot convert string to tuple')
return tuple(seq)


limited_builtins['tuple'] = _limited_tuple
8 changes: 4 additions & 4 deletions src/RestrictedPython/RCompile.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
from compiler.pycodegen import AbstractCompileMode
from compiler.pycodegen import Expression
from compiler.pycodegen import findOp
from compiler.pycodegen import FunctionCodeGenerator
from compiler.pycodegen import FunctionCodeGenerator # noqa
from compiler.pycodegen import Interactive
from compiler.pycodegen import Module
from compiler.pycodegen import ModuleCodeGenerator
Expand Down Expand Up @@ -259,13 +259,13 @@ def parse(self):
if len(f.code.nodes) > 0:
stmt1 = f.code.nodes[0]
if (isinstance(stmt1, c_ast.Discard) and
isinstance(stmt1.expr, c_ast.Const) and
isinstance(stmt1.expr.value, str)):
isinstance(stmt1.expr, c_ast.Const) and
isinstance(stmt1.expr.value, str)):
f.doc = stmt1.expr.value
# The caller may specify that certain variables are globals
# so that they can be referenced before a local assignment.
# The only known example is the variables context, container,
# script, traverse_subpath in PythonScripts.
if self.globals:
f.code.nodes.insert(0, ast.Global(self.globals))
f.code.nodes.insert(0, c_ast.Global(self.globals))
return tree
1 change: 1 addition & 0 deletions src/RestrictedPython/RestrictionMutator.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ def stmtNode(txt):
rmLineno(node)
return node


# The security checks are performed by a set of six functions that
# must be provided by the restricted environment.

Expand Down
7 changes: 6 additions & 1 deletion src/RestrictedPython/Utilities.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
import math
import random
import string
import warnings


# _old_filters = warnings.filters[:]
Expand Down Expand Up @@ -50,6 +49,8 @@ def same_type(arg1, *args):
if getattr(arg, '__class__', type(arg)) is not t:
return 0
return 1


utility_builtins['same_type'] = same_type


Expand All @@ -61,6 +62,8 @@ def test(*args):

if length % 2:
return args[-1]


utility_builtins['test'] = test


Expand Down Expand Up @@ -98,4 +101,6 @@ def reorder(s, with_=None, without=()):
del orig[key]

return result


utility_builtins['reorder'] = reorder
10 changes: 5 additions & 5 deletions src/RestrictedPython/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@
"""RestrictedPython package."""

# Old API --> Old Import Locations
#from RestrictedPython.RCompile import compile_restricted
#from RestrictedPython.RCompile import compile_restricted_eval
#from RestrictedPython.RCompile import compile_restricted_exec
#from RestrictedPython.RCompile import compile_restricted_function
# from RestrictedPython.RCompile import compile_restricted
# from RestrictedPython.RCompile import compile_restricted_eval
# from RestrictedPython.RCompile import compile_restricted_exec
# from RestrictedPython.RCompile import compile_restricted_function

# new API Style
from RestrictedPython.compile import compile_restricted
Expand All @@ -31,4 +31,4 @@
from RestrictedPython.Utilities import utility_builtins


#from RestrictedPython.Eval import RestrictionCapableEval
# from RestrictedPython.Eval import RestrictionCapableEval
14 changes: 9 additions & 5 deletions src/RestrictedPython/compile.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

CompileResult = namedtuple(
'CompileResult', 'code, errors, warnings, used_names')
syntax_error_template = (
'Line {lineno}: {type}: {msg} in on statement: {statement}')


def _compile_restricted_mode(
Expand All @@ -30,7 +32,7 @@ def _compile_restricted_mode(
except (TypeError, ValueError) as e:
errors.append(str(e))
except SyntaxError as v:
errors.append('Line {lineno}: {type}: {msg} in on statement: {statement}'.format(
errors.append(syntax_error_template.format(
lineno=v.lineno,
type=v.__class__.__name__,
msg=v.msg,
Expand All @@ -40,8 +42,8 @@ def _compile_restricted_mode(
policy(errors, warnings, used_names).visit(c_ast)
if not errors:
byte_code = compile(c_ast, filename, mode=mode # ,
#flags=flags,
#dont_inherit=dont_inherit
# flags=flags,
# dont_inherit=dont_inherit
)
return CompileResult(byte_code, tuple(errors), warnings, used_names)

Expand All @@ -52,6 +54,7 @@ def compile_restricted_exec(
flags=0,
dont_inherit=0,
policy=RestrictingNodeTransformer):
"""Compile restricted for the mode `exec`."""
return _compile_restricted_mode(
source,
filename=filename,
Expand All @@ -67,7 +70,7 @@ def compile_restricted_eval(
flags=0,
dont_inherit=0,
policy=RestrictingNodeTransformer):

"""Compile restricted for the mode `eval`."""
return _compile_restricted_mode(
source,
filename=filename,
Expand All @@ -83,6 +86,7 @@ def compile_restricted_single(
flags=0,
dont_inherit=0,
policy=RestrictingNodeTransformer):
"""Compile restricted for the mode `single`."""
return _compile_restricted_mode(
source,
filename=filename,
Expand All @@ -98,7 +102,7 @@ def compile_restricted_function(
flags=0,
dont_inherit=0,
policy=RestrictingNodeTransformer):
"""Compiles a restricted code object for a function.
"""Compile a restricted code object for a function.

The function can be reconstituted using the 'new' module:

Expand Down
25 changes: 16 additions & 9 deletions src/RestrictedPython/transformer.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,17 +107,20 @@ def gen_tmp_name(self):
def error(self, node, info):
"""Record a security error discovered during transformation."""
lineno = getattr(node, 'lineno', None)
self.errors.append('Line {lineno}: {info}'.format(lineno=lineno, info=info))
self.errors.append(
'Line {lineno}: {info}'.format(lineno=lineno, info=info))

def warn(self, node, info):
"""Record a security error discovered during transformation."""
lineno = getattr(node, 'lineno', None)
self.warnings.append('Line {lineno}: {info}'.format(lineno=lineno, info=info))
self.warnings.append(
'Line {lineno}: {info}'.format(lineno=lineno, info=info))

def use_name(self, node, info):
"""Record a security error discovered during transformation."""
lineno = getattr(node, 'lineno', None)
self.used_names.append('Line {lineno}: {info}'.format(lineno=lineno, info=info))
self.used_names.append(
'Line {lineno}: {info}'.format(lineno=lineno, info=info))

def guard_iter(self, node):
"""
Expand Down Expand Up @@ -161,7 +164,8 @@ def gen_unpack_spec(self, tpl):

This spec is used to protect sequence unpacking.
The primary goal of this spec is to tell which elements in a sequence
are sequences again. These 'child' sequences have to be protected again.
are sequences again. These 'child' sequences have to be protected
again.

For example there is a sequence like this:
(a, (b, c), (d, (e, f))) = g
Expand Down Expand Up @@ -307,14 +311,15 @@ def gen_none_node(self):

def gen_lambda(self, args, body):
return ast.Lambda(
args=ast.arguments(args=args, vararg=None, kwarg=None, defaults=[]),
args=ast.arguments(
args=args, vararg=None, kwarg=None, defaults=[]),
body=body)

def gen_del_stmt(self, name_to_del):
return ast.Delete(targets=[ast.Name(name_to_del, ast.Del())])

def transform_slice(self, slice_):
"""Transforms slices into function parameters.
"""Transform slices into function parameters.

ast.Slice nodes are only allowed within a ast.Subscript node.
To use a slice as an argument of ast.Call it has to be converted.
Expand Down Expand Up @@ -433,7 +438,8 @@ def inject_print_collector(self, node, position=0):
printed_used = self.print_info.printed_used

if print_used or printed_used:
# Add '_print = _print_(_getattr_)' add the top of a function/module.
# Add '_print = _print_(_getattr_)' add the top of a
# function/module.
_print = ast.Assign(
targets=[ast.Name('_print', ast.Store())],
value=ast.Call(
Expand Down Expand Up @@ -1281,7 +1287,7 @@ def visit_withitem(self, node):
# Function and class definitions

def visit_FunctionDef(self, node):
"""Checks a function defintion.
"""Check a function defintion.

Checks the name of the function and the arguments.
"""
Expand All @@ -1301,7 +1307,8 @@ def visit_FunctionDef(self, node):
unpacks = []
for index, arg in enumerate(list(node.args.args)):
if isinstance(arg, ast.Tuple):
tmp_target, unpack = self.gen_unpack_wrapper(node, arg, 'param')
tmp_target, unpack = self.gen_unpack_wrapper(
node, arg, 'param')

# Replace the tuple with a single (temporary) parameter.
node.args.args[index] = tmp_target
Expand Down
2 changes: 1 addition & 1 deletion tox.ini
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
[tox]
envlist =
flake8,
coverage-clean,
py27,
py34,
Expand All @@ -8,7 +9,6 @@ envlist =
pypy,
coverage-report,
isort,
#flake8,
skip_missing_interpreters = False

[testenv]
Expand Down