Skip to content
Open
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
3 changes: 3 additions & 0 deletions docs/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ See the [Contributing Guide](contributing.md) for details.

### Fixed

* 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).
* For backwards compatibility in some languages, revert the enforcement of CommonMark
style punctuation rules (#1657).

Expand Down
2 changes: 1 addition & 1 deletion markdown/extensions/attr_list.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ def isheader(elem: Element) -> bool:

class AttrListTreeprocessor(Treeprocessor):

BASE_RE = r'\{\:?[ ]*([^\}\n ][^\n]*)[ ]*\}'
BASE_RE = r'\{\:?[ ]*([^\}\n ][^\n]*)\}'
HEADER_RE = re.compile(r'[ ]+{}[ ]*$'.format(BASE_RE))
BLOCK_RE = re.compile(r'\n[ ]*{}[ ]*$'.format(BASE_RE))
INLINE_RE = re.compile(r'^{}'.format(BASE_RE))
Expand Down
12 changes: 12 additions & 0 deletions tests/test_syntax/extensions/test_attr_list.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,18 @@ def test_backslash_escape_value(self):
'<h1 id="*Foo*"><code>*Foo*</code></h1>'
)

def test_unclosed_curly_with_long_run_of_spaces(self):
"""
An unclosed attribute list followed by a long run of spaces should be
left as plain text, no matter how many trailing spaces there are.

The content and the trailing spaces both match the same part of the
pattern, so without care the regex backtracks quadratically over the

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The spellchecker does not recognize "quadratically" as a valid word. Either the comment needs to be rewritten to not use the word, or the word should be added to the dictionary at .spell-dict.

spaces while failing to find the closing brace.
"""
text = 'foo\n{a' + (' ' * 50000)
self.assertMarkdownRenders(text, f'<p>{text}</p>')

def test_table_td(self):
self.assertMarkdownRenders(
self.dedent(
Expand Down
Loading