Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions docs/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ See the [Contributing Guide](contributing.md) for details.
* Fix quadratic-time regex backtracking in `attr_list` when a block ends with an
unclosed attribute list followed by a long run of spaces, e.g. a line
consisting only of `{` and some text with many trailing spaces (#1656).
* Fix quadratic-time regex backtracking in hash headers when a long run of `#`
characters is followed by more text on the same line.
* Fix regression in `BacktickInlineProcessor` where text could be lost when opening
and closing backticks did not match (#1668).
* Escape the language name in the `codehilite` extension's non-Pygments output to
Expand Down
2 changes: 1 addition & 1 deletion markdown/blockprocessors.py
Original file line number Diff line number Diff line change
Expand Up @@ -458,7 +458,7 @@ class HashHeaderProcessor(BlockProcessor):
""" Process Hash Headers. """

# Detect a header at start of any line in block
RE = re.compile(r'(?:^|\n)(?P<level>#{1,6})(?P<header>(?:\\.|[^\\])*?)#*(?:\n|$)')
RE = re.compile(r'(?:^|\n)(?P<level>#{1,6})(?P<header>(?:\\.|[^\\#]|#+(?=[^#\n]))*?)#*(?:\n|$)')

def test(self, parent: etree.Element, block: str) -> bool:
return bool(self.RE.search(block))
Expand Down
12 changes: 12 additions & 0 deletions tests/test_syntax/blocks/test_headers.py
Original file line number Diff line number Diff line change
Expand Up @@ -779,3 +779,15 @@ def test_unescaped_hash(self):
"""
)
)

def test_long_run_of_hashes_not_at_end(self):
"""
A long run of hashes followed by more text on the same line is part of
the header text and should not be scanned once per hash when looking
for the closing hashes.
"""
hashes = '#' * 20000
self.assertMarkdownRenders(
'# ' + hashes + 'x',
'<h1>' + hashes + 'x</h1>'
)
Loading