From e41e76cd3318d7a689a14be1740a73e087242f0c Mon Sep 17 00:00:00 2001 From: ThiefMaster Date: Fri, 6 Feb 2015 00:34:36 +0100 Subject: [PATCH] Disallow f(x, y=1, z) and similar nonsense Python rejects such function definitions because it doesn't make much sense to have arguments with no default values after arguments with default values. Jinja did allow them, but handled them improperly (associating the default value with the wrong argument). Due to how broken the current behavior is, it makes more sense to reject templates containing such defintions instead of trying to handle them properly. Both cases are going to break existing code containing such definitions, but besides the fact that possibly no such code exists it is better to fail with a clear error than to silently change the values of arguments. This fixes #364 --- CHANGES | 4 ++++ jinja2/parser.py | 2 ++ jinja2/testsuite/core_tags.py | 9 +++++++++ 3 files changed, 15 insertions(+) diff --git a/CHANGES b/CHANGES index ffe0a925..eaa6e6bf 100644 --- a/CHANGES +++ b/CHANGES @@ -21,6 +21,10 @@ Version 2.8 - Implemented a block ``set`` tag. - Default cache size was incrased to 400 from a low 50. - Fixed ``is number`` test to accept long integers in all Python versions. +- Added a check for default arguments followed by non-default arguments. This + change makes ``{% macro m(x, y=1, z) %}...{% endmacro %}`` a syntax error. The + previous behavior for this code was broken anyway (resulting in the default + value being applied to `y`). Version 2.7.3 ------------- diff --git a/jinja2/parser.py b/jinja2/parser.py index 2cf2bd20..d24da180 100644 --- a/jinja2/parser.py +++ b/jinja2/parser.py @@ -314,6 +314,8 @@ class Parser(object): arg.set_ctx('param') if self.stream.skip_if('assign'): defaults.append(self.parse_expression()) + elif defaults: + self.fail('non-default argument follows default argument') args.append(arg) self.stream.expect('rparen') diff --git a/jinja2/testsuite/core_tags.py b/jinja2/testsuite/core_tags.py index ac0eb4cb..e1cff3bf 100644 --- a/jinja2/testsuite/core_tags.py +++ b/jinja2/testsuite/core_tags.py @@ -244,6 +244,15 @@ class MacrosTestCase(JinjaTestCase): {{ m() }}|{{ m('a') }}|{{ m('a', 'b') }}|{{ m(1, 2, 3) }}''') assert tmpl.render() == '||c|d|a||c|d|a|b|c|d|1|2|3|d' + def test_arguments_defaults_nonsense(self): + self.assert_raises(TemplateSyntaxError, self.env.from_string, '''\ +{% macro m(a, b=1, c) %}a={{ a }}, b={{ b }}, c={{ c }}{% endmacro %}''') + + def test_caller_defaults_nonsense(self): + self.assert_raises(TemplateSyntaxError, self.env.from_string, '''\ +{% macro a() %}{{ caller() }}{% endmacro %} +{% call(x, y=1, z) a() %}{% endcall %}''') + def test_varargs(self): tmpl = self.env.from_string('''\ {% macro test() %}{{ varargs|join('|') }}{% endmacro %}\ -- 2.47.2