]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-135661: Fix abrupt closing of empty comment in HTMLParser (GH-153007)
authorSerhiy Storchaka <storchaka@gmail.com>
Sat, 4 Jul 2026 12:05:07 +0000 (15:05 +0300)
committerGitHub <noreply@github.com>
Sat, 4 Jul 2026 12:05:07 +0000 (15:05 +0300)
An abruptly closed empty comment ("<!-->" or "<!--->") no longer extends
up to a later "-->" in the same feed() call.

test_htmlparser now also feeds each string source as a single chunk, in
addition to one character at a time, to exercise different input buffering.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Lib/html/parser.py
Lib/test/test_htmlparser.py
Misc/NEWS.d/next/Library/2026-07-04-13-00-00.gh-issue-135661.CIkADG.rst [new file with mode: 0644]

index 80fb8c3f929f6b62e0f665a6a781949755398e64..38ddf9ef442d3682f19fcb4bbf67bb4d400817b1 100644 (file)
@@ -387,9 +387,11 @@ class HTMLParser(_markupbase.ParserBase):
     def parse_comment(self, i, report=True):
         rawdata = self.rawdata
         assert rawdata.startswith('<!--', i), 'unexpected call to parse_comment()'
-        match = commentclose.search(rawdata, i+4)
+        # An empty comment is abruptly closed by the first ">" or "->",
+        # taking priority over a later "-->" or "--!>" close.
+        match = commentabruptclose.match(rawdata, i+4)
         if not match:
-            match = commentabruptclose.match(rawdata, i+4)
+            match = commentclose.search(rawdata, i+4)
             if not match:
                 return -1
         if report:
index e4eff1ea17a670bc15f253e263e185afefbffb5c..6b7624f11505d927cfc91b7b40c5a00c5448222c 100644 (file)
@@ -116,6 +116,11 @@ class TestCaseBase(unittest.TestCase):
                    *, collector=None, convert_charrefs=False):
         if collector is None:
             collector = self.get_collector(convert_charrefs=convert_charrefs)
+            if isinstance(source, str):
+                # Also feed the whole string at once, not just character by
+                # character (below), to exercise different input buffering.
+                self._run_check([source], expected_events,
+                                convert_charrefs=convert_charrefs)
         parser = collector
         for s in source:
             parser.feed(s)
@@ -593,6 +598,9 @@ text
                 '<!-- <!-- nested --> -->'
                 '<!--<!-->'
                 '<!--<!--!>'
+                # abruptly closed empty comment must not swallow later text
+                '<!-->x-->'
+                '<!--->y-->'
         )
         expected = [('comment', " I'm a valid comment "),
                     ('comment', 'me too!'),
@@ -613,6 +621,8 @@ text
                     ('comment', ' <!-- nested '), ('data', ' -->'),
                     ('comment', '<!'),
                     ('comment', '<!'),
+                    ('comment', ''), ('data', 'x-->'),
+                    ('comment', ''), ('data', 'y-->'),
         ]
         self._run_check(html, expected)
 
diff --git a/Misc/NEWS.d/next/Library/2026-07-04-13-00-00.gh-issue-135661.CIkADG.rst b/Misc/NEWS.d/next/Library/2026-07-04-13-00-00.gh-issue-135661.CIkADG.rst
new file mode 100644 (file)
index 0000000..26a912a
--- /dev/null
@@ -0,0 +1,3 @@
+Fix :class:`html.parser.HTMLParser`: an abruptly closed empty comment
+(``<!-->`` or ``<!--->``) no longer extends up to a later ``-->`` in the same
+:meth:`~html.parser.HTMLParser.feed` call.