From 1fc52011bbdee6e0b301eaceb6c11fd861f25c4a Mon Sep 17 00:00:00 2001 From: DarkTinia <1106116020@qq.com> Date: Wed, 18 Jan 2023 04:54:18 -0800 Subject: [PATCH 1/3] repair a ReDoS vulnerability in markdown2.py --- lib/markdown2.py | 54 ++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 50 insertions(+), 4 deletions(-) diff --git a/lib/markdown2.py b/lib/markdown2.py index 112fa707..a44e92ae 100755 --- a/lib/markdown2.py +++ b/lib/markdown2.py @@ -105,6 +105,7 @@ import sys import re +import re2 import logging from hashlib import sha256 import optparse @@ -2246,17 +2247,62 @@ def _do_tg_spoiler(self, text): text = self._tg_spoiler_re.sub(r"\1", text) return text - _strong_re = re.compile(r"(\*\*|__)(?=\S)(.+?[*_]*)(?<=\S)\1", re.S) + #_strong_re = re.compile(r"(\*\*|__)(?=\S)(.+?[*_]*)(?<=\S)\1", re.S) _em_re = re.compile(r"(\*|_)(?=\S)(.+?)(?<=\S)\1", re.S) - _code_friendly_strong_re = re.compile(r"\*\*(?=\S)(.+?[*_]*)(?<=\S)\*\*", re.S) + #_code_friendly_strong_re = re.compile(r"\*\*(?=\S)(.+?[*_]*)(?<=\S)\*\*", re.S) _code_friendly_em_re = re.compile(r"\*(?=\S)(.+?)(?<=\S)\*", re.S) + + def _safe_strong_re_sub(self,text): + import re2 + #(\*\*|__)(?=\S)(.+?[*_]*)(?<=\S)\1 + _code_friendly_strong_re = re2.compile(r"(?s)(\*\*|__)(.+?[*_]*)(\*\*|__)") + m = _code_friendly_strong_re.search(text) + tmpText = "" + while True: + if m == None: + tmpText += text + return tmpText + else: + group2Text = m.group(2) + # lookaround‘s constraints + if re2.match("\S.*", group2Text) and re2.match(".*\S", group2Text) and m.group(1) == m.group(3): + tmpText += text[0:m.span()[0]] + "" + group2Text + "" + text = text[m.span()[1]:] + m = _code_friendly_strong_re.search(text) + else: + return tmpText + text + + def _safe_code_friendly_strong_re_sub(self,text): + # **abc**v**edf ** + #\*\*(?=\S)(.+?[*_]*)(?<=\S)\*\* + _code_friendly_strong_re = re2.compile(r"(?s)\*\*(.+?[*_]*)\*\*") + m = _code_friendly_strong_re.search(text) + tmpText = "" + while True: + if m == None: + tmpText += text + return tmpText + else: + group1Text = m.group(1) + # lookaround‘s constraints + if re2.match("\S.*",group1Text) and re2.match(".*\S",group1Text): + tmpText += text[0:m.span()[0]] + "" + group1Text + "" + text = text[m.span()[1]:] + m = _code_friendly_strong_re.search(text) + else: + return tmpText + text + + + def _do_italics_and_bold(self, text): # must go first: if "code-friendly" in self.extras: - text = self._code_friendly_strong_re.sub(r"\1", text) + #text =self._code_friendly_strong_re(r"\1",text) + text = self._safe_code_friendly_strong_re_sub(text) text = self._code_friendly_em_re.sub(r"\1", text) else: - text = self._strong_re.sub(r"\2", text) + #text = self._strong_re.sub(r"\2", text) + text = self._safe_strong_re_sub(text) text = self._em_re.sub(r"\2", text) return text From ea615a9382587da258a657909ff873cbfb7d712f Mon Sep 17 00:00:00 2001 From: DarkTinia <1106116020@qq.com> Date: Wed, 18 Jan 2023 20:48:02 -0800 Subject: [PATCH 2/3] add an install_requires in setup.py --- setup.py | 1 + 1 file changed, 1 insertion(+) diff --git a/setup.py b/setup.py index e7c43ad3..d9b23c3a 100755 --- a/setup.py +++ b/setup.py @@ -56,6 +56,7 @@ }, description="A fast and complete Python implementation of Markdown", python_requires=">=3.5, <4", + install_requires=['pyre2'], extras_require=extras_require, classifiers=classifiers.strip().split("\n"), long_description="""markdown2: A fast and complete Python implementation of Markdown. From 0eafad6ad784d168eb20238c6aed7a76744ba642 Mon Sep 17 00:00:00 2001 From: Crozzers Date: Sun, 24 Sep 2023 19:09:14 +0100 Subject: [PATCH 3/3] Remove requirement for third party regex library --- lib/markdown2.py | 58 +++++------------------------------------------- setup.py | 1 - 2 files changed, 6 insertions(+), 53 deletions(-) diff --git a/lib/markdown2.py b/lib/markdown2.py index a44e92ae..4f1f2f61 100755 --- a/lib/markdown2.py +++ b/lib/markdown2.py @@ -105,7 +105,6 @@ import sys import re -import re2 import logging from hashlib import sha256 import optparse @@ -2241,68 +2240,23 @@ def _do_strike(self, text): def _do_underline(self, text): text = self._underline_re.sub(r"\1", text) return text - + _tg_spoiler_re = re.compile(r"\|\|\s?(.+?)\s?\|\|", re.S) def _do_tg_spoiler(self, text): text = self._tg_spoiler_re.sub(r"\1", text) return text - #_strong_re = re.compile(r"(\*\*|__)(?=\S)(.+?[*_]*)(?<=\S)\1", re.S) - _em_re = re.compile(r"(\*|_)(?=\S)(.+?)(?<=\S)\1", re.S) - #_code_friendly_strong_re = re.compile(r"\*\*(?=\S)(.+?[*_]*)(?<=\S)\*\*", re.S) + _strong_re = re.compile(r"(\*\*|__)(?=\S)(.*\S)\1", re.S) + _em_re = re.compile(r"(\*|_)(?=\S)(.*?\S)\1", re.S) + _code_friendly_strong_re = re.compile(r"\*\*(?=\S)(.+?[*_]*)(?<=\S)\*\*", re.S) _code_friendly_em_re = re.compile(r"\*(?=\S)(.+?)(?<=\S)\*", re.S) - - def _safe_strong_re_sub(self,text): - import re2 - #(\*\*|__)(?=\S)(.+?[*_]*)(?<=\S)\1 - _code_friendly_strong_re = re2.compile(r"(?s)(\*\*|__)(.+?[*_]*)(\*\*|__)") - m = _code_friendly_strong_re.search(text) - tmpText = "" - while True: - if m == None: - tmpText += text - return tmpText - else: - group2Text = m.group(2) - # lookaround‘s constraints - if re2.match("\S.*", group2Text) and re2.match(".*\S", group2Text) and m.group(1) == m.group(3): - tmpText += text[0:m.span()[0]] + "" + group2Text + "" - text = text[m.span()[1]:] - m = _code_friendly_strong_re.search(text) - else: - return tmpText + text - - def _safe_code_friendly_strong_re_sub(self,text): - # **abc**v**edf ** - #\*\*(?=\S)(.+?[*_]*)(?<=\S)\*\* - _code_friendly_strong_re = re2.compile(r"(?s)\*\*(.+?[*_]*)\*\*") - m = _code_friendly_strong_re.search(text) - tmpText = "" - while True: - if m == None: - tmpText += text - return tmpText - else: - group1Text = m.group(1) - # lookaround‘s constraints - if re2.match("\S.*",group1Text) and re2.match(".*\S",group1Text): - tmpText += text[0:m.span()[0]] + "" + group1Text + "" - text = text[m.span()[1]:] - m = _code_friendly_strong_re.search(text) - else: - return tmpText + text - - - def _do_italics_and_bold(self, text): # must go first: if "code-friendly" in self.extras: - #text =self._code_friendly_strong_re(r"\1",text) - text = self._safe_code_friendly_strong_re_sub(text) + text = self._code_friendly_strong_re.sub(r"\1", text) text = self._code_friendly_em_re.sub(r"\1", text) else: - #text = self._strong_re.sub(r"\2", text) - text = self._safe_strong_re_sub(text) + text = self._strong_re.sub(r"\2", text) text = self._em_re.sub(r"\2", text) return text diff --git a/setup.py b/setup.py index d9b23c3a..e7c43ad3 100755 --- a/setup.py +++ b/setup.py @@ -56,7 +56,6 @@ }, description="A fast and complete Python implementation of Markdown", python_requires=">=3.5, <4", - install_requires=['pyre2'], extras_require=extras_require, classifiers=classifiers.strip().split("\n"), long_description="""markdown2: A fast and complete Python implementation of Markdown.