From e3f095b086225d3bd3eae6266ec1a0580a5d49e8 Mon Sep 17 00:00:00 2001 From: Tim Martin Date: Sun, 18 Dec 2016 08:08:53 +0000 Subject: [PATCH] Fixed #26478 -- Made {% for %} reject invalid unpacking vars with quotes or vertical bars. --- django/template/defaulttags.py | 11 ++++++----- tests/template_tests/syntax_tests/test_for.py | 18 ++++++++++++++++++ 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/django/template/defaulttags.py b/django/template/defaulttags.py index 71fcbbaab3..d35e80cfa9 100644 --- a/django/template/defaulttags.py +++ b/django/template/defaulttags.py @@ -17,10 +17,10 @@ from django.utils.safestring import mark_safe from .base import ( BLOCK_TAG_END, BLOCK_TAG_START, COMMENT_TAG_END, COMMENT_TAG_START, - SINGLE_BRACE_END, SINGLE_BRACE_START, VARIABLE_ATTRIBUTE_SEPARATOR, - VARIABLE_TAG_END, VARIABLE_TAG_START, Context, Node, NodeList, - TemplateSyntaxError, VariableDoesNotExist, kwarg_re, - render_value_in_context, token_kwargs, + FILTER_SEPARATOR, SINGLE_BRACE_END, SINGLE_BRACE_START, + VARIABLE_ATTRIBUTE_SEPARATOR, VARIABLE_TAG_END, VARIABLE_TAG_START, + Context, Node, NodeList, TemplateSyntaxError, VariableDoesNotExist, + kwarg_re, render_value_in_context, token_kwargs, ) from .defaultfilters import date from .library import Library @@ -816,9 +816,10 @@ def do_for(parser, token): raise TemplateSyntaxError("'for' statements should use the format" " 'for x in y': %s" % token.contents) + invalid_chars = frozenset((' ', '"', "'", FILTER_SEPARATOR)) loopvars = re.split(r' *, *', ' '.join(bits[1:in_index])) for var in loopvars: - if not var or ' ' in var: + if not var or not invalid_chars.isdisjoint(var): raise TemplateSyntaxError("'for' tag received an invalid argument:" " %s" % token.contents) diff --git a/tests/template_tests/syntax_tests/test_for.py b/tests/template_tests/syntax_tests/test_for.py index afdffb892b..cf556f1b71 100644 --- a/tests/template_tests/syntax_tests/test_for.py +++ b/tests/template_tests/syntax_tests/test_for.py @@ -87,6 +87,24 @@ class ForTagTests(SimpleTestCase): with self.assertRaisesMessage(TemplateSyntaxError, msg): self.engine.render_to_string('for-tag-unpack08', {'items': (('one', 1), ('two', 2))}) + @setup({'double-quote': '{% for "k" in items %}{{ "k" }}/{% endfor %}'}) + def test_unpack_double_quote(self): + msg = """'for' tag received an invalid argument: for "k" in items""" + with self.assertRaisesMessage(TemplateSyntaxError, msg): + self.engine.render_to_string('double-quote', {'items': (1, 2)}) + + @setup({'single-quote': "{% for 'k' in items %}{{ k }}/{% endfor %}"}) + def test_unpack_single_quote(self): + msg = """'for' tag received an invalid argument: for 'k' in items""" + with self.assertRaisesMessage(TemplateSyntaxError, msg): + self.engine.render_to_string('single-quote', {'items': (1, 2)}) + + @setup({'vertical-bar': '{% for k|upper in items %}{{ k|upper }}/{% endfor %}'}) + def test_unpack_vertical_bar(self): + msg = "'for' tag received an invalid argument: for k|upper in items" + with self.assertRaisesMessage(TemplateSyntaxError, msg): + self.engine.render_to_string('vertical-bar', {'items': (1, 2)}) + @setup({'for-tag-unpack09': '{% for val in items %}{{ val.0 }}:{{ val.1 }}/{% endfor %}'}) def test_for_tag_unpack09(self): """