Describe the bug
With texmath_plugin, a display-math block that opens inside a blockquote and whose closing delimiter only appears after the blockquote makes md.parse() loop forever, with memory growing until the process is killed.
Minimal reproduction
from markdown_it import MarkdownIt
from mdit_py_plugins.texmath import texmath_plugin
md = MarkdownIt("commonmark").use(texmath_plugin) # delimiters="dollars"
md.parse("> $$ a=1\n\n$$\n") # never returns
Every delimiter set is affected:
delimiters |
input |
dollars, kramdown |
"> $$ a=1\n\n$$\n" |
brackets |
"> \[ a=1\n\n\]\n" |
gitlab, julia |
"> ```math a=1\n\n```\n" |
Nested containers too ("> > $$ a=1\n\n$$\n", "- > $$ a=1\n\n$$\n"). Lists on their own do not hang.
Reproduced with mdit-py-plugins 0.6.1 and master (519953d), markdown-it-py 4.2.0 and master (6f58654), Python 3.12, Windows 11.
Cause
make_block_func in mdit_py_plugins/texmath/index.py matches the rule's regex against state.src[begin:], the rest of the whole source, so the match can end past endLine. The loop that looks for the closing line then finds nothing and state.line is never advanced, but the rule still pushes a token and returns True. The block tokenizer calls it again on the same line, forever, pushing a new token each time.
It is the same failure mode that #117 fixed for amsmath in 0.4.2. It is not covered by #148, which fixes regex backtracking.
Suggested fix
Look for the closing line only within [begLine, endLine), and return False before pushing any token when the match ends outside the current block: no auto-closing, as in amsmath. A PR with this change and regression tests follows.
markdown-it JS turns this situation into an error since 13.0.2 (block rule didn't increment state.line, markdown-it/markdown-it#847); markdown-it-py has no such guard, so I'm opening a separate issue there.
Describe the bug
With
texmath_plugin, a display-math block that opens inside a blockquote and whose closing delimiter only appears after the blockquote makesmd.parse()loop forever, with memory growing until the process is killed.Minimal reproduction
Every delimiter set is affected:
delimitersdollars,kramdown"> $$ a=1\n\n$$\n"brackets"> \[ a=1\n\n\]\n"gitlab,julia"> ```math a=1\n\n```\n"Nested containers too (
"> > $$ a=1\n\n$$\n","- > $$ a=1\n\n$$\n"). Lists on their own do not hang.Reproduced with mdit-py-plugins 0.6.1 and
master(519953d), markdown-it-py 4.2.0 andmaster(6f58654), Python 3.12, Windows 11.Cause
make_block_funcinmdit_py_plugins/texmath/index.pymatches the rule's regex againststate.src[begin:], the rest of the whole source, so the match can end pastendLine. The loop that looks for the closing line then finds nothing andstate.lineis never advanced, but the rule still pushes a token and returnsTrue. The block tokenizer calls it again on the same line, forever, pushing a new token each time.It is the same failure mode that #117 fixed for
amsmathin 0.4.2. It is not covered by #148, which fixes regex backtracking.Suggested fix
Look for the closing line only within
[begLine, endLine), and returnFalsebefore pushing any token when the match ends outside the current block: no auto-closing, as inamsmath. A PR with this change and regression tests follows.markdown-it JS turns this situation into an error since 13.0.2 (
block rule didn't increment state.line, markdown-it/markdown-it#847); markdown-it-py has no such guard, so I'm opening a separate issue there.