From 925760291d6efec64fda6e9dd1fd9cfbd5be068c Mon Sep 17 00:00:00 2001
From: Mike Bayer <mike_mp@zzzcomputing.com>
Date: Mon, 29 Aug 2022 12:28:52 -0400
Subject: [PATCH] fix tag regexp to match quoted groups correctly

Fixed issue in lexer where the regexp used to match tags would not
correctly interpret quoted sections individually. While this parsing issue
still produced the same expected tag structure later on, the mis-handling
of quoted sections was also subject to a regexp crash if a tag had a large
number of quotes within its quoted sections.

Fixes: #366
Change-Id: I74e0d71ff7f419970711a7cd51adcf1bb90a44c0

Upstream-Status: Backport [https://github.com/sqlalchemy/mako/commit/925760291d6efec64fda6e9dd1fd9cfbd5be068c]

Signed-off-by: <narpat.mali@windriver.com>

---
 doc/build/unreleased/366.rst |  9 +++++++++
 mako/lexer.py                | 12 ++++++++----
 test/test_lexer.py           | 21 +++++++++++++++++----
 3 files changed, 34 insertions(+), 8 deletions(-)
 create mode 100644 doc/build/unreleased/366.rst

--- /dev/null
+++ Mako-1.1.6/doc/build/unreleased/366.rst
@@ -0,0 +1,9 @@
+.. change::
+    :tags: bug, lexer
+    :tickets: 366
+
+    Fixed issue in lexer where the regexp used to match tags would not
+    correctly interpret quoted sections individually. While this parsing issue
+    still produced the same expected tag structure later on, the mis-handling
+    of quoted sections was also subject to a regexp crash if a tag had a large
+    number of quotes within its quoted sections.
\ No newline at end of file
--- Mako-1.1.6.orig/mako/lexer.py
+++ Mako-1.1.6/mako/lexer.py
@@ -295,20 +295,24 @@ class Lexer(object):
         return self.template
 
     def match_tag_start(self):
-        match = self.match(
-            r"""
+        reg = r"""
             \<%     # opening tag
 
             ([\w\.\:]+)   # keyword
 
-            ((?:\s+\w+|\s*=\s*|".*?"|'.*?')*)  # attrname, = \
+            ((?:\s+\w+|\s*=\s*|"[^"]*?"|'[^']*?'|\s*,\s*)*)  # attrname, = \
                                                #        sign, string expression
+                                               # comma is for backwards compat
+                                               # identified in #366
 
             \s*     # more whitespace
 
             (/)?>   # closing
 
-            """,
+        """
+
+        match = self.match(
+            reg,
             re.I | re.S | re.X,
         )
 
--- Mako-1.1.6.orig/test/test_lexer.py
+++ Mako-1.1.6/test/test_lexer.py
@@ -1,5 +1,7 @@
 import re
 
+import pytest
+
 from mako import compat
 from mako import exceptions
 from mako import parsetree
@@ -146,6 +148,10 @@ class LexerTest(TemplateTest):
         """
         self.assertRaises(exceptions.CompileException, Lexer(template).parse)
 
+    def test_tag_many_quotes(self):
+        template = "<%0" + '"' * 3000
+        assert_raises(exceptions.SyntaxException, Lexer(template).parse)
+
     def test_unmatched_tag(self):
         template = """
         <%namespace name="bar">
@@ -432,9 +438,16 @@ class LexerTest(TemplateTest):
             ),
         )
 
-    def test_pagetag(self):
-        template = """
-            <%page cached="True", args="a, b"/>
+    @pytest.mark.parametrize("comma,numchars", [(",", 48), ("", 47)])
+    def test_pagetag(self, comma, numchars):
+        # note that the comma here looks like:
+        # <%page cached="True", args="a, b"/>
+        # that's what this test has looked like for decades, however, the
+        # comma there is not actually the right syntax.  When issue #366
+        # was fixed, the reg was altered to accommodate for this comma to allow
+        # backwards compat
+        template = f"""
+            <%page cached="True"{comma} args="a, b"/>
 
             some template
         """
@@ -453,7 +466,7 @@ class LexerTest(TemplateTest):
 
             some template
         """,
-                        (2, 48),
+                        (2, numchars),
                     ),
                 ],
             ),
