Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package python-markdown2 for 
openSUSE:Factory checked in at 2026-10-16 20:09:45
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-markdown2 (Old)
 and      /work/SRC/openSUSE:Factory/.python-markdown2.new.3698736 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-markdown2"

Fri Oct 16 20:09:45 2026 rev:20 rq:1385152 version:2.5.5

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-markdown2/python-markdown2.changes        
2026-03-29 20:01:48.200178499 +0200
+++ 
/work/SRC/openSUSE:Factory/.python-markdown2.new.3698736/python-markdown2.changes
   2026-10-16 20:13:44.888403974 +0200
@@ -1,0 +2,6 @@
+Fri Oct 16 08:02:15 UTC 2026 - Dirk Müller <[email protected]>
+
+- add 0001-Avoid-overlapping-regex-matches-that-trigger-excessi.patch
+  (bsc#1285724, CVE-2026-88753)
+
+-------------------------------------------------------------------

New:
----
  0001-Avoid-overlapping-regex-matches-that-trigger-excessi.patch

----------(New B)----------
  New:
- add 0001-Avoid-overlapping-regex-matches-that-trigger-excessi.patch
  (bsc#1285724, CVE-2026-88753)
----------(New E)----------

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-markdown2.spec ++++++
--- /var/tmp/diff_new_pack.It9EOa/_old  2026-10-16 20:13:45.922447397 +0200
+++ /var/tmp/diff_new_pack.It9EOa/_new  2026-10-16 20:13:45.923447439 +0200
@@ -25,6 +25,7 @@
 Group:          Development/Languages/Python
 URL:            https://github.com/trentm/python-markdown2
 Source:         
https://files.pythonhosted.org/packages/source/m/markdown2/markdown2-%{version}.tar.gz
+Patch1:         0001-Avoid-overlapping-regex-matches-that-trigger-excessi.patch
 BuildRequires:  %{python_module pip}
 BuildRequires:  %{python_module pygments}
 BuildRequires:  %{python_module setuptools}

++++++ 0001-Avoid-overlapping-regex-matches-that-trigger-excessi.patch ++++++
>From b0885d4e845ec9c6453ac0b0c7c2928b5f74eb27 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Dirk=20M=C3=BCller?= <[email protected]>
Date: Fri, 16 Oct 2026 09:52:17 +0200
Subject: [PATCH] Avoid overlapping regex matches that trigger excessive
 backtracking
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Constrained the metadata key definition to r'[ \t]*[^\s:\r\n][^:\r\n]*', 
ensuring keys cannot match colons or newlines and cannot backtrack across 
key/value
delimiters.
Kept simple single-line values bounded by [^\n]*\n?.
Simplified to r"^-[ \t]*([^\n]*)(?:\n((?:[ \t]+[^\n]+\n?)+))?", removing the 
overlapping space quantifiers before [:-].
Updated parse_structured_value to support both 2-tuple and 3-tuple matches for 
full backward compatibility.

Added tests

Verification:

  ┌────────────┬────────────┬───────────┐
  │ Input Size │ Before Fix │ After Fix │
  ├────────────┼────────────┼───────────┤
  │ 8 KB       │ ~0.4 s     │ ~0.003 s  │
  │ 16 KB      │ ~1.6 s     │ ~0.0003 s │
  │ 32 KB      │ ~6.2 s     │ ~0.0005 s │
  │ 64 KB      │ ~24.0 s    │ ~0.0008 s │
  │ 128 KB     │ ~91.0 s    │ ~0.0015 s │
  └────────────┴────────────┴───────────┘
---
 lib/markdown2.py       | 42 ++++++++++++++++++++++++------------------
 test/test_markdown2.py | 18 ++++++++++++++++++
 test/test_redos.py     | 10 ++++++++++
 3 files changed, 52 insertions(+), 18 deletions(-)

Index: markdown2-2.5.5/lib/markdown2.py
===================================================================
--- markdown2-2.5.5.orig/lib/markdown2.py
+++ markdown2-2.5.5/lib/markdown2.py
@@ -608,17 +608,16 @@ class Markdown:
             (?:
                 {1}:(?:\n+[ \t]+.*)+  # indented lists
             )|(?:
-                (?:{1}:\s+>(?:\n\s+.*)+?)  # multiline long descriptions
-                (?=\n{1}:\s*.*\n|\s*\Z)  # match up until the start of the 
next key:value definition or the end of the input text
+                {1}:\s+>(?:\n+[ \t]+.*)+  # multiline long descriptions
             )|(?:
-                {1}:(?! >).*\n?  # simple key:value pair, leading spaces 
allowed
+                {1}:[^\n]*\n?  # simple key:value pair, leading spaces allowed
             )
         ){0}  # optional closing fence
-        '''.format(r'(?:---[\ \t]*\n)?', r'[\S \t]*\w[\S \t]*\s*'), 
re.MULTILINE | re.VERBOSE
+        '''.format(r'(?:---[\ \t]*\n)?', r'[ \t]*[^\s:\r\n][^:\r\n]*'), 
re.MULTILINE | re.VERBOSE
     )
 
     _key_val_list_pat = re.compile(
-        r"^-(?:[ \t]*([^\n]*)(?:[ \t]*[:-][ \t]*(\S+))?)(?:\n((?:[ 
\t]+[^\n]+\n?)+))?",
+        r"^-[ \t]*([^\n]*)(?:\n((?:[ \t]+[^\n]+\n?)+))?",
         re.MULTILINE,
     )
     _key_val_dict_pat = re.compile(
@@ -650,21 +649,28 @@ class Markdown:
             # List
             if vs.startswith("-"):
                 r: list[Any] = []
-                # the regex used has multiple capturing groups, so
-                # returned type from findall will be List[List[str]]
-                match: list[str]
+                # returned type from findall will be list[tuple[str, ...]]
                 for match in re.findall(self._key_val_list_pat, vs):
-                    if match[0] and not match[1] and not match[2]:
-                        r.append(match[0].strip())
-                    elif match[0] == ">" and not match[1] and match[2]:
-                        r.append(match[2].strip())
-                    elif match[0] and match[1]:
-                        r.append({match[0].strip(): match[1].strip()})
-                    elif not match[0] and not match[1] and match[2]:
-                        r.append(parse_structured_value(match[2]))
+                    if len(match) == 2:
+                        val, block = match[0], match[1]
+                        if val and not block:
+                            r.append(val.strip())
+                        elif val == ">" and block:
+                            r.append(block.strip())
+                        elif not val and block:
+                            r.append(parse_structured_value(block))
                     else:
-                        # Broken case
-                        pass
+                        if match[0] and not match[1] and not match[2]:
+                            r.append(match[0].strip())
+                        elif match[0] == ">" and not match[1] and match[2]:
+                            r.append(match[2].strip())
+                        elif match[0] and match[1]:
+                            r.append({match[0].strip(): match[1].strip()})
+                        elif not match[0] and not match[1] and match[2]:
+                            r.append(parse_structured_value(match[2]))
+                        else:
+                            # Broken case
+                            pass
 
                 return r
 
Index: markdown2-2.5.5/test/test_markdown2.py
===================================================================
--- markdown2-2.5.5.orig/test/test_markdown2.py
+++ markdown2-2.5.5/test/test_markdown2.py
@@ -267,6 +267,24 @@ versions of markdown2.py this was pathol
             '<h2>%s</h2>\n' % ko)
     test_russian.tags = ["unicode", "issue3"]
 
+    def test_metadata_redos_resilience(self):
+        import time
+        doc = "---\nkey: -" + " " * 32000 + "\n---\n\n# hello\n"
+        t = time.time()
+        result = markdown2.markdown(doc, extras=['metadata'])
+        self.assertLess(time.time() - t, 1.0)
+        self.assertEqual(result.metadata, {'key': '-'})
+    test_metadata_redos_resilience.tags = ["metadata", "redos"]
+
+    def test_metadata_list_redos_resilience(self):
+        import time
+        doc = "---\nitems:\n  - item" + " " * 32000 + "\n---\n\n# hello\n"
+        t = time.time()
+        result = markdown2.markdown(doc, extras=['metadata'])
+        self.assertLess(time.time() - t, 1.0)
+        self.assertEqual(result.metadata, {'items': ['item']})
+    test_metadata_list_redos_resilience.tags = ["metadata", "redos"]
+
     def test_toc_with_persistent_object(self):
         """
         Tests that the toc is the same every time it's run on HTML, even if 
the Markdown object isn't disposed of.
Index: markdown2-2.5.5/test/test_redos.py
===================================================================
--- markdown2-2.5.5.orig/test/test_redos.py
+++ markdown2-2.5.5/test/test_redos.py
@@ -43,6 +43,14 @@ def issue_668():
     return 'a_b **x***y* c_d'
 
 
+def issue_metadata_redos():
+    return "---\nkey: -" + " " * 32000 + "\n---\n\n# hello\n"
+
+
+def issue_metadata_list_redos():
+    return "---\nitems:\n  - " + " " * 32000 + "\n---\n\n# hello\n"
+
+
 # whack everything in a dict for easy lookup later on
 CASES = {
     fn.__name__: (fn, extras)
@@ -54,6 +62,8 @@ CASES = {
         (issue493, None),
         (issue_633, None),
         (issue_668, ['code-friendly']),
+        (issue_metadata_redos, ['metadata']),
+        (issue_metadata_list_redos, ['metadata']),
     ]
 }
 

Reply via email to