lepture / mistune

A fast yet powerful Python Markdown parser with renderers and plugins.
http://mistune.lepture.com/
BSD 3-Clause "New" or "Revised" License
2.59k stars 250 forks source link

Exception caused in custom plugin altering parsing rules #376

Open maxking opened 10 months ago

maxking commented 10 months ago

We have a custom plugin that we use to disable all the parsing rules, except block_quote. The way we have implemented this is:

def plugin_disable_markdown(md):
    """This plugin disables most of the rules in mistune."""
    md.block.rules = ['block_quote']
    md.block.block_quote_rules = ['block_quote']
    md.block.list_rules = ['block_quote']
    md.inline.rules = ['inline_html', 'auto_link']

This causes an exception in the situation when the block_quote nesting depth increases the max_nesting_depth value (6 is the default in mistune).

So, a text like:

>> >> >> foo bar

will raise an exception like below (few lines of traceback is removed, full traceback can be found here)

  File "/opt/mailman/mm/venv/lib/python3.9/site-packages/hyperkitty/templatetags/decorate.py", line 36, in render
    return mark_safe(text_renderer(content))
  File "/opt/mailman/mm/venv/lib/python3.9/site-packages/mistune/markdown.py", line 110, in __call__
    return self.parse(s)[0]
  File "/opt/mailman/mm/venv/lib/python3.9/site-packages/mistune/markdown.py", line 85, in parse
    self.block.parse(state)
  File "/opt/mailman/mm/venv/lib/python3.9/site-packages/mistune/block_parser.py", line 446, in parse
    end_pos = self.parse_method(m, state)
  File "/opt/mailman/mm/venv/lib/python3.9/site-packages/mistune/core.py", line 168, in parse_method
    return func(m, state)
  File "/opt/mailman/mm/venv/lib/python3.9/site-packages/mistune/block_parser.py", line 369, in parse_block_quote
    self.parse(child, rules)
  File "/opt/mailman/mm/venv/lib/python3.9/site-packages/mistune/block_parser.py", line 446, in parse
    end_pos = self.parse_method(m, state)
  File "/opt/mailman/mm/venv/lib/python3.9/site-packages/mistune/core.py", line 168, in parse_method
    return func(m, state)
  File "/opt/mailman/mm/venv/lib/python3.9/site-packages/mistune/block_parser.py", line 369, in parse_block_quote
    self.parse(child, rules)
  File "/opt/mailman/mm/venv/lib/python3.9/site-packages/mistune/block_parser.py", line 446, in parse
    end_pos = self.parse_method(m, state)
  File "/opt/mailman/mm/venv/lib/python3.9/site-packages/mistune/core.py", line 168, in parse_method
    return func(m, state)
  File "/opt/mailman/mm/venv/lib/python3.9/site-packages/mistune/block_parser.py", line 369, in parse_block_quote
    self.parse(child, rules)
  File "/opt/mailman/mm/venv/lib/python3.9/site-packages/mistune/block_parser.py", line 446, in parse
    end_pos = self.parse_method(m, state)
  File "/opt/mailman/mm/venv/lib/python3.9/site-packages/mistune/core.py", line 168, in parse_method
    return func(m, state)
  File "/opt/mailman/mm/venv/lib/python3.9/site-packages/mistune/block_parser.py", line 369, in parse_block_quote
    self.parse(child, rules)
  File "/opt/mailman/mm/venv/lib/python3.9/site-packages/mistune/block_parser.py", line 446, in parse
    end_pos = self.parse_method(m, state)
  File "/opt/mailman/mm/venv/lib/python3.9/site-packages/mistune/core.py", line 168, in parse_method
    return func(m, state)
  File "/opt/mailman/mm/venv/lib/python3.9/site-packages/mistune/block_parser.py", line 369, in parse_block_quote
    self.parse(child, rules)
  File "/opt/mailman/mm/venv/lib/python3.9/site-packages/mistune/block_parser.py", line 446, in parse
    end_pos = self.parse_method(m, state)
  File "/opt/mailman/mm/venv/lib/python3.9/site-packages/mistune/core.py", line 168, in parse_method
    return func(m, state)
  File "/opt/mailman/mm/venv/lib/python3.9/site-packages/mistune/block_parser.py", line 369, in parse_block_quote
    self.parse(child, rules)
  File "/opt/mailman/mm/venv/lib/python3.9/site-packages/mistune/block_parser.py", line 446, in parse
    end_pos = self.parse_method(m, state)
  File "/opt/mailman/mm/venv/lib/python3.9/site-packages/mistune/core.py", line 167, in parse_method
    func = self._methods[m.lastgroup]
KeyError: None
maxking commented 10 months ago

My suspicion is that after 5 levels of parsing blockquote, the block.block_quote_rules removes block_quote so that becomes an empty set of rules []. And since there aren't any rules m.lastgroup has no groups so it returns None value causing the above exception.

IMO, this can be guarded against with a None check of try-except (so control flow is altered only in case of special case of block_quote_rules being empty, which isn't typical).

Happy to submit a patch a try-except to guard works.

lepture commented 9 months ago

@maxking A pull request is welcome.