Skip to content

Commit 94aafb7

Browse files
committed
Fix infinite loop when text contains multiple unclosed comments
The updatepos() override was resetting the parser position to 0, causing infinite loops when multiple bogus/unclosed comments appeared in the input (e.g., `</` or `<!--` followed by non-standard characters). Now tracks the position of the triggering `<` and advances past it instead of rewinding to the start of the buffer. Fixes #1578
1 parent 89112c2 commit 94aafb7

File tree

2 files changed

+20
-2
lines changed

2 files changed

+20
-2
lines changed

markdown/htmlparser.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ def __init__(self, md: Markdown, *args, **kwargs):
111111
self.lineno_start_cache = [0]
112112

113113
self.override_comment_update = False
114+
self.override_comment_start = 0
114115

115116
# This calls self.reset
116117
super().__init__(*args, **kwargs)
@@ -124,6 +125,7 @@ def reset(self):
124125
self._cache: list[str] = []
125126
self.cleandoc: list[str] = []
126127
self.lineno_start_cache = [0]
128+
self.override_comment_start = 0
127129

128130
super().reset()
129131

@@ -276,15 +278,17 @@ def handle_comment(self, data: str):
276278
i = self.line_offset + self.offset + len(data) + 4
277279
if self.rawdata[i:i + 3] != '-->':
278280
self.handle_data('<')
281+
pos = self.line_offset + self.offset
282+
self.override_comment_start = pos - 1 if self.rawdata[pos - 1:pos] == '<' else pos
279283
self.override_comment_update = True
280284
return
281285
self.handle_empty_tag('<!--{}-->'.format(data), is_block=True)
282286

283287
def updatepos(self, i: int, j: int) -> int:
284288
if self.override_comment_update:
285289
self.override_comment_update = False
286-
i = 0
287-
j = 1
290+
i = self.override_comment_start
291+
j = self.override_comment_start + 1
288292
return super().updatepos(i, j)
289293

290294
def handle_decl(self, data: str):

tests/test_syntax/blocks/test_html_blocks.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1684,3 +1684,17 @@ def test_noname_tag(self):
16841684
"""
16851685
)
16861686
)
1687+
1688+
def test_multiple_bogus_comments_no_hang(self):
1689+
"""Test that multiple bogus comments (</` patterns) don't cause infinite loop."""
1690+
self.assertMarkdownRenders(
1691+
'`</` and `</`',
1692+
'<p><code>&lt;/</code> and <code>&lt;/</code></p>'
1693+
)
1694+
1695+
def test_multiple_unclosed_comments_no_hang(self):
1696+
"""Test that multiple unclosed comments don't cause infinite loop."""
1697+
self.assertMarkdownRenders(
1698+
'<!-- and <!--',
1699+
'<p>&lt;!-- and &lt;!--</p>'
1700+
)

0 commit comments

Comments
 (0)