From b6b499d8ecbd443f715f29d496d0144d0dfebdee Mon Sep 17 00:00:00 2001
From: bhanugoudm041 <bhanugoudm041@gmail.com>
Date: Tue, 26 May 2026 22:16:19 -0400
Subject: [PATCH] fix: resolve O(n^2) DoS in parse_link_text (CWE-400)

---
 src/mistune/helpers.py       |  6 +++---
 src/mistune/inline_parser.py | 14 +++++++++-----
 2 files changed, 12 insertions(+), 8 deletions(-)

Index: mistune-3.1.3/src/mistune/inline_parser.py
===================================================================
--- mistune-3.1.3.orig/src/mistune/inline_parser.py
+++ mistune-3.1.3/src/mistune/inline_parser.py
@@ -126,8 +126,13 @@ class InlineParser(Parser[InlineState]):
         text = None
         label, end_pos = parse_link_label(state.src, pos)
         if label is None:
+            if pos <= state.no_close_bracket_before:
+                state.append_token({"type": "text", "raw": marker})
+                return pos
             text, end_pos = parse_link_text(state.src, pos)
             if text is None:
+                if end_pos and end_pos > state.no_close_bracket_before:
+                    state.no_close_bracket_before = end_pos
                 return None
 
         assert end_pos is not None
Index: mistune-3.1.3/src/mistune/core.py
===================================================================
--- mistune-3.1.3.orig/src/mistune/core.py
+++ mistune-3.1.3/src/mistune/core.py
@@ -119,6 +119,7 @@ class InlineState:
         self.in_link = False
         self.in_emphasis = False
         self.in_strong = False
+        self.no_close_bracket_before: int = 0  # high-water mark for DoS mitigation
 
     def prepend_token(self, token: Dict[str, Any]) -> None:
         """Insert token before the last token."""
Index: mistune-3.1.3/src/mistune/helpers.py
===================================================================
--- mistune-3.1.3.orig/src/mistune/helpers.py
+++ mistune-3.1.3/src/mistune/helpers.py
@@ -107,7 +107,7 @@ def unescape_char(text: str) -> str:
     return _ESCAPE_CHAR_RE.sub(r"\1", text)
 
 
-def parse_link_text(src: str, pos: int) -> Union[Tuple[str, int], Tuple[None, None]]:
+def parse_link_text(src: str, pos: int) -> Union[Tuple[str, int], Tuple[None, int]]:
     level = 1
     found = False
     start_pos = pos
