Skip to content

Stop definition list nesting short of the recursion limit - #1701

Open
rahul05ranjan wants to merge 1 commit into
Python-Markdown:masterfrom
rahul05ranjan:def-list-recursion-guard
Open

rahul05ranjan wants to merge 1 commit into
Python-Markdown:masterfrom
rahul05ranjan:def-list-recursion-guard

Conversation

@rahul05ranjan

Copy link
Copy Markdown

Problem

The def_list extension raises an uncaught RecursionError on a flat document of term/definition pairs without blank lines (#1700):

markdown.markdown('term\n: definition\n' * 600, extensions=['def_list'])
# RecursionError: maximum recursion depth exceeded

DefListProcessor.run calls parseBlocks on the definition content, and with no blank lines each remaining term\n: definition pair nests one level deeper — so only ~5 KB of input (linear in recursion depth) reaches the interpreter's limit.

Change

DefListProcessor.test now declines to run near the recursion limit — the same guard BlockquoteProcessor.test already applies — so the remaining markers are kept as text, exactly as for blockquotes and (per #1685) lists.

Verification

  • 3 new tests in TestDefListNestingLimit (tests/test_syntax/extensions/test_def_list.py), following the conventions of Stop list nesting short of the recursion limit #1685's TestListNestingLimit: the recursionlimit(120) nesting-stops test and the 600-pair no-crash test fail on master (RecursionError), the shallow-nesting render test pins existing behavior; all pass with this change
  • Full suite: 868 passed + 24 subtests (111 skipped: pyyaml-dependent, unchanged) with this change vs 866 on master — the delta is the new tests; tests/test_syntax/extensions/test_md_in_html.py excluded locally (its TestSuite helper class doesn't collect under the host's pytest 9, an environment quirk unrelated to this change)
  • Run with system Python 3.13 and the project's dependencies from PyPI wheels on PYTHONPATH (pygments 2.21.0; markdown built locally with the repo's own setup.py for entry-point loading); nothing installed

Fixes #1700

DefListProcessor.run calls parseBlocks on the definition content, which
can contain further definitions, so a document of flat term/definition
pairs without blank lines nests once per pair and raises an uncaught
RecursionError from only ~5 KB of input.

DefListProcessor.test now declines to run near the recursion limit, the
same guard BlockquoteProcessor already uses; the remaining markers are
kept as text.

Fixes Python-Markdown#1700

Co-authored-by: rahul05ranjan <11793455+rahul05ranjan@users.noreply.github.com>
@waylan waylan added the needs-review Needs to be reviewed and/or approved. label Nov 9, 2026

@waylan waylan left a comment

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.

This looks good. Thank you. If you make the minor fix noted below and add a changelog entry, I'll merge this.

self.assertIn('term', result)

def test_deeply_nested_definitions_do_not_raise(self):
# Around 5 KB of input, which raised RecursionError before the limit was applied.

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.

RecursionError should be in a code span to avoid tripping up the spellchecker.

@waylan waylan added requires-changes Awaiting updates after a review. and removed needs-review Needs to be reviewed and/or approved. labels Nov 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

requires-changes Awaiting updates after a review.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

def_list extension: uncaught RecursionError (DoS) on flat term/definition pairs

2 participants