Quadratic-time inline-link parsing: many unclosed [...]( cause a CPU DoS
Les mainteneurs répondent en général sous 3 jours
Évaluation
- Difficulté
- 4/5
- Temps estimé
- 3-5 jours
- Accessibilité débutants
- 30/100
- Type d'issue
- Bug
- Clarté
- Plutôt claire
- Activité
- À l'abandon
- Stack technique
- python
- Domaine
- performance
Piste de recherche
Reproduce first with the timing snippet in the report, then profile "[a](" * 4000 to confirm the cost sits in _find_balanced and the self._inline_link_title.search call inside parse_inline_anchor_or_image in markdown2.py. Read how the inline-link loop rebuilds text per resolved link, since the issue warns a per-text paren cache regresses "[a](b) " * 4000 badly; check PR #751 before duplicating work. Done means the unclosed-( benchmark scales roughly linearly while the existing test suite (including the link/image cases) still passes and no link-heavy slowdown appears.
Rédigé par le modèle d'indexation à partir du texte de l'issue.
Description
Summary
markdown2.markdown() is quadratic in the number of unclosed ( inline-link destinations. A small input of repeated [a]( (or  grows with the square of its length and pins a CPU. This is the same denial-of-service class as #741 / #707 / #633, with a different trigger (the inline-link destination scan).
Reproduce
import time, markdown2
for n in (1000, 2000, 4000):
doc = "[a](" * n
t0 = time.perf_counter()
markdown2.markdown(doc)
print(f"{n:5d} links {len(doc):6d} bytes {time.perf_counter()-t0:6.2f}s")
1000 links 4000 bytes 0.19s
2000 links 8000 bytes 0.82s
4000 links 16000 bytes 3.16s
Doubling the input roughly quadruples the time. " behaves the same, slightly slower.
Where the time goes
cProfile on "[a](" * 4000 (3.39s total):
ncalls tottime function
3999 2.363 markdown2.py:_find_balanced
4001 0.988 {method 'search' of re.Pattern} # self._inline_link_title.search
parse_inline_anchor_or_image calls _find_balanced(text, end_idx, "(", ")") for every [...](. When the ( never closes, _find_balanced scans to the end of the text, and the link loop runs it once per [...](, so the total work is O(n²). The following self._inline_link_title.search(text, idx, end_idx) with end_idx == len(text) is the other O(n) per call.
A note for whoever fixes it
This is more subtle than it looks. The obvious fix (precompute the balanced-paren positions once per text and reuse them, like a cache) is correct but regresses link-heavy documents badly, because the link loop rebuilds text every time a link resolves, so a per-text cache is invalidated on every resolved link. I measured "[a](b) " * 4000 going from 0.20s to ~87s with that approach. A good fix needs to avoid the full rescan without relying on a per-text cache, e.g. bailing out of both the _find_balanced scan and the title search as soon as the destination has no closing ). I am happy to help test a patch.
Environment
markdown2 2.5.x (PyPI) and master; CPython 3.12, Linux.
- Langage dominant
- Python
- Étoiles
- 2.8k
- Forks
- 477
- Merge moyen
- 4 j 6 h
- PR mergées (30 j)
- 12
Préparer son environnement
Ce projet ne fournit ni conteneur de développement, ni Dockerfile, ni guide de contribution : l'installation est à votre charge. Commencez par son README, et consultez notre guide de la première contribution pour les étapes générales.
Par où commencer
- Lisez l'issue en entier, puis le guide de contribution du projet.
- Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
- Forkez le dépôt et travaillez sur une branche.
- Ouvrez une pull request qui référence le numéro de l'issue.
Autres issues de trentm/python-markdown2
-
Add py.typed markerPeut-être pris @mac-agent l’a pris il y a 220 jours. Ouverte
Difficulté 2/5 1-3 heures Accessibilité débutants 72/100
trentm/python-markdown2#696 ·
Les mainteneurs répondent en général sous 3 jours
-
Difficulté 2/5 1-3 heures Accessibilité débutants 53/100
trentm/python-markdown2#763 ·
Les mainteneurs répondent en général sous 3 jours
-
Code spans that wrap onto the next line are no longer recognised (regression from the #702 fix)Peut-être pris @awais-ur-rehman l’a pris il y a 5 jours. Ouverte
Difficulté 4/5 1-2 jours Accessibilité débutants 55/100
trentm/python-markdown2#756 ·
Les mainteneurs répondent en général sous 3 jours
-
link-patterns extra replaces matches inside inline HTML tags and destroys email auto-linksPeut-être pris @rahul05ranjan l’a pris il y a 7 jours. OuverteBug
Difficulté 3/5 1-2 jours Accessibilité débutants 30/100
trentm/python-markdown2#752 ·
Les mainteneurs répondent en général sous 3 jours
-
Bug
Difficulté 3/5 1-2 jours Accessibilité débutants 58/100
trentm/python-markdown2#688 · 4 commentaires ·
Les mainteneurs répondent en général sous 3 jours
Toutes les issues de trentm/python-markdown2
Issues similaires
-
Difficulté 2/5 1-3 heures Accessibilité débutants 72/100
huggingface/deep-rl-class#723 ·
-
[tool] bug: Qwen3 XML tool parser raises on `...` argument values (Ellipsis is not JSON serializable)Peut-être pris @super-yuki l’a pris aujourd’hui. Ouverte
Difficulté 2/5 1-3 heures Accessibilité débutants 87/100
verl-project/verl#8559 ·
Les mainteneurs répondent en général sous 1 jour
-
bug
Difficulté 2/5 1-3 heures Accessibilité débutants 75/100
TencentCloud/octop-harness#228 ·
Les mainteneurs répondent en général sous 1 jour
-
Difficulté 2/5 1-3 heures Accessibilité débutants 78/100
google/osv-scalibr#2585 ·
Les mainteneurs répondent en général sous 2 jours
-
Difficulté 2/5 1-3 heures Accessibilité débutants 85/100
NousResearch/hermes-agent#149323 ·
Les mainteneurs répondent en général sous 1 jour