From 68bcb6229b16d69fda60af9de7ca376f160b27b7 Mon Sep 17 00:00:00 2001 From: LuisFigueroaG Date: Wed, 7 Oct 2026 13:08:40 -0300 Subject: [PATCH 1/2] Fix empty list items being parsed as nested lists A list item with nothing after the marker swallowed the next line as its content, so "1. \n2. " produced a nested, unclosed list instead of two empty items. Allow the item text to be empty. Fixes #167 --- CHANGES.md | 1 + lib/markdown2.py | 2 +- test/tm-cases/empty_list_items_issue167.html | 38 +++++++++++++++++++ test/tm-cases/empty_list_items_issue167.text | 26 +++++++++++++ .../xss_smuggling_spans_in_image_attrs.html | 4 +- 5 files changed, 67 insertions(+), 4 deletions(-) create mode 100644 test/tm-cases/empty_list_items_issue167.html create mode 100644 test/tm-cases/empty_list_items_issue167.text diff --git a/CHANGES.md b/CHANGES.md index 8911b5cb..bf85cbdf 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -17,6 +17,7 @@ - [pull #720] Add `wiki-links` extra for `[[Page Name]]` style links (#221) - [pull #722] Harden URL safety checks and sanitization in safe mode (#721) - [pull #728] Fix XSS from zero-padded colon entities in link URLs (#726) +- Fix empty list items being parsed as nested lists (#167) ## python-markdown2 2.5.5 diff --git a/lib/markdown2.py b/lib/markdown2.py index b3c29847..8952c00a 100755 --- a/lib/markdown2.py +++ b/lib/markdown2.py @@ -1873,7 +1873,7 @@ def _do_lists(self, text: str) -> str: (\n)? # leading line = \1 (^[ \t]*) # leading whitespace = \2 (?P{}) [ \t]+ # list marker = \3 - ((?:.+?) # list item text = \4 + ((?:.*?) # list item text = \4 (may be empty) (\n{{1,2}})) # eols = \5 (?= \n* (\Z | \2 (?P{}) [ \t]+)) '''.format(_marker_any, _marker_any), diff --git a/test/tm-cases/empty_list_items_issue167.html b/test/tm-cases/empty_list_items_issue167.html new file mode 100644 index 00000000..4f080c02 --- /dev/null +++ b/test/tm-cases/empty_list_items_issue167.html @@ -0,0 +1,38 @@ +
    +
  1. +
  2. +
+ +

Empty bullet items:

+ +
    +
  • +
  • +
+ +

An empty item between others:

+ +
    +
  • foo
  • +
  • +
  • bar
  • +
+ +

An empty numbered item:

+ +
    +
  1. foo
  2. +
  3. +
  4. bar
  5. +
+ +

Empty items in a sub-list:

+ +
    +
  • foo +
      +
    • +
    • +
  • +
  • bar
  • +
diff --git a/test/tm-cases/empty_list_items_issue167.text b/test/tm-cases/empty_list_items_issue167.text new file mode 100644 index 00000000..23f10c55 --- /dev/null +++ b/test/tm-cases/empty_list_items_issue167.text @@ -0,0 +1,26 @@ + 1. + 2. + +Empty bullet items: + +- +- + +An empty item between others: + +- foo +- +- bar + +An empty numbered item: + +1. foo +2. +3. bar + +Empty items in a sub-list: + +- foo + - + - +- bar diff --git a/test/tm-cases/xss_smuggling_spans_in_image_attrs.html b/test/tm-cases/xss_smuggling_spans_in_image_attrs.html index 15d99a49..c0837ef9 100644 --- a/test/tm-cases/xss_smuggling_spans_in_image_attrs.html +++ b/test/tm-cases/xss_smuggling_spans_in_image_attrs.html @@ -9,10 +9,8 @@

x

    -
  • -
      +
    • onerror=alert(origin) )
    • -