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
14 changes: 0 additions & 14 deletions src/RestrictedPython/tests/security_in_syntax.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,6 @@
# Each function in this module is compiled using compile_restricted().


def overrideGuardWithLambda():
lambda o, _getattr=None: o


def overrideGuardWithArgument():
def f(_getattr=None):
pass


def check_getattr_in_lambda(arg=lambda _getattr=(lambda ob, name: name):
_getattr):
42


def except_using_bad_name():
try:
foo
Expand Down
2 changes: 1 addition & 1 deletion src/RestrictedPython/transformer.py
Original file line number Diff line number Diff line change
Expand Up @@ -1313,7 +1313,7 @@ def visit_FunctionDef(self, node):
return node

def visit_Lambda(self, node):
"""Checks a lambda definition."""
"""Check a lambda definition."""
self.check_function_argument_names(node)

node = self.node_contents_visit(node)
Expand Down
199 changes: 157 additions & 42 deletions tests/test_transformer.py
Original file line number Diff line number Diff line change
Expand Up @@ -326,7 +326,7 @@ def test_transformer__RestrictingNodeTransformer__visit_Attribute__7(compile, mo
@pytest.mark.skipif(IS_PY2,
reason="exec is a statement in Python 2")
@pytest.mark.parametrize(*compile)
def test_transformer__RestrictingNodeTransformer__visit_Call__1(compile):
def test_transformer__RestrictingNodeTransformer__visit_Call__2(compile):
"""It is an error if the code call the `exec` function."""
code, errors, warnings, used_names = compile(EXEC_FUNCTION)
assert ("Line 2: Exec calls are not allowed.",) == errors
Expand All @@ -339,7 +339,7 @@ def no_eval():


@pytest.mark.parametrize(*compile)
def test_transformer__RestrictingNodeTransformer__visit_Call__2(compile):
def test_transformer__RestrictingNodeTransformer__visit_Call__3(compile):
"""It is an error if the code call the `eval` function."""
code, errors, warnings, used_names = compile(EVAL_FUNCTION)
if compile is RestrictedPython.compile.compile_restricted_exec:
Expand Down Expand Up @@ -757,42 +757,94 @@ def test_transformer__RestrictingNodeTransformer__visit_Call(compile, mocker):
_apply_.reset_mock()


@pytest.mark.parametrize(*compile)
def test_transformer__RestrictingNodeTransformer__visit_FunctionDef_1(compile):
err_msg = 'Line 1: "_bad" is an invalid variable ' \
'name because it starts with "_"'
functiondef_err_msg = 'Line 1: "_bad" is an invalid variable ' \
'name because it starts with "_"'


@pytest.mark.parametrize(*compile)
def test_transformer__RestrictingNodeTransformer__visit_FunctionDef__1(
compile):
"""It prevents function arguments starting with `_`."""
code, errors = compile("def foo(_bad): pass")[:2]
# RestrictedPython.compile.compile_restricted_exec on Python 2 renders
# the error message twice. This is necessary as otherwise *_bad and **_bad
# would be allowed.
assert functiondef_err_msg in errors
assert code is None
assert errors[0] == err_msg


@pytest.mark.parametrize(*compile)
def test_transformer__RestrictingNodeTransformer__visit_FunctionDef__2(
compile):
"""It prevents function keyword arguments starting with `_`."""
code, errors = compile("def foo(_bad=1): pass")[:2]
# RestrictedPython.compile.compile_restricted_exec on Python 2 renders
# the error message twice. This is necessary as otherwise *_bad and **_bad
# would be allowed.
assert functiondef_err_msg in errors
assert code is None
assert errors[0] == err_msg


@pytest.mark.parametrize(*compile)
def test_transformer__RestrictingNodeTransformer__visit_FunctionDef__3(
compile):
"""It prevents function * arguments starting with `_`."""
code, errors = compile("def foo(*_bad): pass")[:2]
assert errors == (functiondef_err_msg,)
assert code is None
assert errors[0] == err_msg


@pytest.mark.parametrize(*compile)
def test_transformer__RestrictingNodeTransformer__visit_FunctionDef__4(
compile):
"""It prevents function ** arguments starting with `_`."""
code, errors = compile("def foo(**_bad): pass")[:2]
assert errors == (functiondef_err_msg,)
assert code is None
assert errors[0] == err_msg

if IS_PY2:
code, errors = compile("def foo((a, _bad)): pass")[:2]
assert code is None
assert errors[0] == err_msg

# The old one did not support nested checks.
if compile is RestrictedPython.compile.compile_restricted_exec:
code, errors = compile("def foo(a, (c, (_bad, c))): pass")[:2]
assert code is None
assert errors[0] == err_msg
@pytest.mark.skipif(
IS_PY3,
reason="tuple parameter unpacking is gone in Python 3")
@pytest.mark.parametrize(*compile)
def test_transformer__RestrictingNodeTransformer__visit_FunctionDef__5(
compile):
"""It prevents function arguments starting with `_` in tuples."""
code, errors = compile("def foo((a, _bad)): pass")[:2]
# RestrictedPython.compile.compile_restricted_exec on Python 2 renders
# the error message twice. This is necessary as otherwise *_bad and **_bad
# would be allowed.
assert functiondef_err_msg in errors
assert code is None


if IS_PY3:
code, errors = compile("def foo(good, *, _bad): pass")[:2]
@pytest.mark.skipif(
IS_PY3,
reason="tuple parameter unpacking is gone in Python 3")
@pytest.mark.parametrize(*compile)
def test_transformer__RestrictingNodeTransformer__visit_FunctionDef__6(
compile):
"""It prevents function arguments starting with `_` in tuples."""
# The old `compile` breaks with tuples in function arguments:
if compile is RestrictedPython.compile.compile_restricted_exec:
code, errors = compile("def foo(a, (c, (_bad, c))): pass")[:2]
# RestrictedPython.compile.compile_restricted_exec on Python 2 renders
# the error message twice. This is necessary as otherwise *_bad and
# **_bad would be allowed.
assert functiondef_err_msg in errors
assert code is None
assert errors[0] == err_msg


@pytest.mark.skipif(
IS_PY2,
reason="There is no single `*` argument in Python 2")
@pytest.mark.parametrize(*compile)
def test_transformer__RestrictingNodeTransformer__visit_FunctionDef__7(
compile):
"""It prevents `_` function arguments together with a single `*`."""
code, errors = compile("def foo(good, *, _bad): pass")[:2]
assert errors == (functiondef_err_msg,)
assert code is None


NESTED_SEQ_UNPACK = """
Expand Down Expand Up @@ -851,42 +903,105 @@ def test_transformer__RestrictingNodeTransformer__visit_FunctionDef_2(compile, m
_getiter_.reset_mock()


@pytest.mark.parametrize(*compile)
def test_transformer__RestrictingNodeTransformer__visit_Lambda_1(compile):
err_msg = 'Line 1: "_bad" is an invalid variable ' \
'name because it starts with "_"'
lambda_err_msg = 'Line 1: "_bad" is an invalid variable ' \
'name because it starts with "_"'


@pytest.mark.parametrize(*compile)
def test_transformer__RestrictingNodeTransformer__visit_Lambda__1(compile):
"""It prevents arguments starting with `_`."""
code, errors = compile("lambda _bad: None")[:2]
# RestrictedPython.compile.compile_restricted_exec on Python 2 renders
# the error message twice. This is necessary as otherwise *_bad and **_bad
# would be allowed.
assert lambda_err_msg in errors
assert code is None
assert errors[0] == err_msg


@pytest.mark.parametrize(*compile)
def test_transformer__RestrictingNodeTransformer__visit_Lambda__2(compile):
"""It prevents keyword arguments starting with `_`."""
code, errors = compile("lambda _bad=1: None")[:2]
# RestrictedPython.compile.compile_restricted_exec on Python 2 renders
# the error message twice. This is necessary as otherwise *_bad and **_bad
# would be allowed.
assert lambda_err_msg in errors
assert code is None
assert errors[0] == err_msg


@pytest.mark.parametrize(*compile)
def test_transformer__RestrictingNodeTransformer__visit_Lambda__3(compile):
"""It prevents * arguments starting with `_`."""
code, errors = compile("lambda *_bad: None")[:2]
assert errors == (lambda_err_msg,)
assert code is None
assert errors[0] == err_msg


@pytest.mark.parametrize(*compile)
def test_transformer__RestrictingNodeTransformer__visit_Lambda__4(compile):
"""It prevents ** arguments starting with `_`."""
code, errors = compile("lambda **_bad: None")[:2]
assert errors == (lambda_err_msg,)
assert code is None
assert errors[0] == err_msg

if IS_PY2:
# The old one did not support tuples at all.
if compile is RestrictedPython.compile.compile_restricted_exec:
code, errors = compile("lambda (a, _bad): None")[:2]
assert code is None
assert errors[0] == err_msg

code, errors = compile("lambda (a, (c, (_bad, c))): None")[:2]
assert code is None
assert errors[0] == err_msg
@pytest.mark.skipif(
IS_PY3,
reason="tuple parameter unpacking is gone in Python 3")
@pytest.mark.parametrize(*compile)
def test_transformer__RestrictingNodeTransformer__visit_Lambda__5(compile):
"""It prevents arguments starting with `_` in tuple unpacking."""
# The old `compile` breaks with tuples in arguments:
if compile is RestrictedPython.compile.compile_restricted_exec:
code, errors = compile("lambda (a, _bad): None")[:2]
# RestrictedPython.compile.compile_restricted_exec on Python 2 renders
# the error message twice. This is necessary as otherwise *_bad and
# **_bad would be allowed.
assert lambda_err_msg in errors
assert code is None

if IS_PY3:
code, errors = compile("lambda good, *, _bad: None")[:2]

@pytest.mark.skipif(
IS_PY3,
reason="tuple parameter unpacking is gone in Python 3")
@pytest.mark.parametrize(*compile)
def test_transformer__RestrictingNodeTransformer__visit_Lambda__6(compile):
"""It prevents arguments starting with `_` in nested tuple unpacking."""
# The old `compile` breaks with tuples in arguments:
if compile is RestrictedPython.compile.compile_restricted_exec:
code, errors = compile("lambda (a, (c, (_bad, c))): None")[:2]
# RestrictedPython.compile.compile_restricted_exec on Python 2 renders
# the error message twice. This is necessary as otherwise *_bad and
# **_bad would be allowed.
assert lambda_err_msg in errors
assert code is None
assert errors[0] == err_msg


@pytest.mark.skipif(
IS_PY2,
reason="There is no single `*` argument in Python 2")
@pytest.mark.parametrize(*compile)
def test_transformer__RestrictingNodeTransformer__visit_Lambda__7(compile):
"""It prevents arguments starting with `_` together with a single `*`."""
code, errors = compile("lambda good, *, _bad: None")[:2]
assert errors == (lambda_err_msg,)
assert code is None


BAD_ARG_IN_LAMBDA = """\
def check_getattr_in_lambda(arg=lambda _bad=(lambda ob, name: name): _bad2):
42
"""


@pytest.mark.parametrize(*compile)
def test_transformer__RestrictingNodeTransformer__visit_Lambda__8(compile):
"""It prevents arguments starting with `_` in weird lambdas."""
code, errors = compile(BAD_ARG_IN_LAMBDA)[:2]
# RestrictedPython.compile.compile_restricted_exec finds both invalid
# names, while the old implementation seems to abort after the first.
assert lambda_err_msg in errors
assert code is None


@pytest.mark.skipif(
Expand Down