From 510dcce56c6ad04b1fe5a3592b8071f2b61646d9 Mon Sep 17 00:00:00 2001 From: Kurt McKee Date: Fri, 31 Jul 2026 09:45:57 -0500 Subject: [PATCH 1/2] Demonstrate trailing content in an end tag fails to close the tag --- tests/test_sgmllib.py | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/tests/test_sgmllib.py b/tests/test_sgmllib.py index c9be3d6..9eb4725 100644 --- a/tests/test_sgmllib.py +++ b/tests/test_sgmllib.py @@ -484,6 +484,33 @@ def test_endtag_closes_innermost_matching_tag(nested_tag_collector): assert nested_tag_collector.stack == ["a"] +@pytest.mark.parametrize( + "trailing_text", + ( + " bonus", + "/", + "=x", + ";", + ",", + ), +) +def test_endtag_with_trailing_content_still_closes_tag( + cdata_event_collector, trailing_text +): + """Verify that a closing tag with trailing content still closes the tag.""" + + cdata_event_collector.check_events( + f"contentafter", + [ + ("starttag", "cdata", []), + ("data", "content"), + ("endtag", "cdata"), + ("data", "after"), + ], + ) + assert cdata_event_collector.stack == [] + + # XXX These tests have been disabled by prefixing their names with # an underscore. The first two exercise outstanding bugs in the # sgmllib module, and the third exhibits questionable behavior From db6143226e1b4fefe5868ba643ee09dd08b46422 Mon Sep 17 00:00:00 2001 From: Kurt McKee Date: Fri, 31 Jul 2026 10:25:01 -0500 Subject: [PATCH 2/2] Close tags more correctly, even if the end tag has trailing text --- ...tmckee_fix_closing_tags_with_trailing_content.rst | 7 +++++++ src/feedparser_sgmllib/__init__.py | 2 ++ tests/test_sgmllib.py | 12 ++++++++++++ 3 files changed, 21 insertions(+) create mode 100644 changelog.d/20260731_095409_kurtmckee_fix_closing_tags_with_trailing_content.rst diff --git a/changelog.d/20260731_095409_kurtmckee_fix_closing_tags_with_trailing_content.rst b/changelog.d/20260731_095409_kurtmckee_fix_closing_tags_with_trailing_content.rst new file mode 100644 index 0000000..7e7ccbc --- /dev/null +++ b/changelog.d/20260731_095409_kurtmckee_fix_closing_tags_with_trailing_content.rst @@ -0,0 +1,7 @@ +Fixed +----- + +* Close tags more correctly, even if the end tag has trailing text. + + For example, ```` now closes ```` correctly. + The trailing content is not available to parsers. diff --git a/src/feedparser_sgmllib/__init__.py b/src/feedparser_sgmllib/__init__.py index 27e832d..be16a40 100644 --- a/src/feedparser_sgmllib/__init__.py +++ b/src/feedparser_sgmllib/__init__.py @@ -361,6 +361,8 @@ def finish_starttag( # Internal -- finish processing of end tag def finish_endtag(self, tag: str) -> None: + if (match := tagfind.match(tag)) is not None: + tag = match.group(0) if not tag: found = len(self.stack) - 1 if found < 0: diff --git a/tests/test_sgmllib.py b/tests/test_sgmllib.py index 9eb4725..8e327cf 100644 --- a/tests/test_sgmllib.py +++ b/tests/test_sgmllib.py @@ -511,6 +511,18 @@ def test_endtag_with_trailing_content_still_closes_tag( assert cdata_event_collector.stack == [] +def test_endtag_with_no_valid_tag_name_does_not_close_open_tag(nested_tag_collector): + """Verify invalid tag names do not close any open tags.""" + + nested_tag_collector.feed("contentafter") + + assert nested_tag_collector.events == [ + ("start_a", []), + ("unknown_endtag", "123"), + ] + assert nested_tag_collector.stack == ["a"] + + # XXX These tests have been disabled by prefixing their names with # an underscore. The first two exercise outstanding bugs in the # sgmllib module, and the third exhibits questionable behavior