From 7d09936fd788ca2c8b7b0516f7249fdee7250c30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adrian=20Schr=C3=B6ter?= Date: Tue, 5 Mar 2024 18:05:06 +0100 Subject: [PATCH] Sync from SUSE:ALP:Source:Standard:1.0 python-Django revision fb4dfe21e6fe0c7578e7172d216dfe99 --- CVE-2024-27351.patch | 121 ++++++++++++++++++++++++++++++++++++++++++ python-Django.changes | 5 ++ python-Django.spec | 2 + 3 files changed, 128 insertions(+) create mode 100644 CVE-2024-27351.patch diff --git a/CVE-2024-27351.patch b/CVE-2024-27351.patch new file mode 100644 index 0000000..c594ae6 --- /dev/null +++ b/CVE-2024-27351.patch @@ -0,0 +1,121 @@ +From 2d173757922183f7e9b79d31fd4ccd9086cc6ce2 Mon Sep 17 00:00:00 2001 +From: Shai Berger +Date: Mon, 19 Feb 2024 13:56:37 +0100 +Subject: [PATCH] [4.2.x] Fixed CVE-2024-27351 -- Prevented potential ReDoS in + Truncator.words(). + +Thanks Seokchan Yoon for the report. + +Co-Authored-By: Mariusz Felisiak +--- + django/utils/text.py | 57 ++++++++++++++++++++++++++++++++-- + docs/releases/3.2.25.txt | 8 +++++ + docs/releases/4.2.11.txt | 8 +++++ + tests/utils_tests/test_text.py | 26 ++++++++++++++++ + 4 files changed, 97 insertions(+), 2 deletions(-) + +Index: Django-4.2.6/django/utils/text.py +=================================================================== +--- Django-4.2.6.orig/django/utils/text.py ++++ Django-4.2.6/django/utils/text.py +@@ -23,8 +23,61 @@ def capfirst(x): + return x[0].upper() + x[1:] + + +-# Set up regular expressions +-re_words = _lazy_re_compile(r"<[^>]+?>|([^<>\s]+)", re.S) ++# ----- Begin security-related performance workaround ----- ++ ++# We used to have, below ++# ++# re_words = _lazy_re_compile(r"<[^>]+?>|([^<>\s]+)", re.S) ++# ++# But it was shown that this regex, in the way we use it here, has some ++# catastrophic edge-case performance features. Namely, when it is applied to ++# text with only open brackets "<<<...". The class below provides the services ++# and correct answers for the use cases, but in these edge cases does it much ++# faster. ++re_notag = _lazy_re_compile(r"([^<>\s]+)", re.S) ++re_prt = _lazy_re_compile(r"<|([^<>\s]+)", re.S) ++ ++ ++class WordsRegex: ++ @staticmethod ++ def search(text, pos): ++ # Look for "<" or a non-tag word. ++ partial = re_prt.search(text, pos) ++ if partial is None or partial[1] is not None: ++ return partial ++ ++ # "<" was found, look for a closing ">". ++ end = text.find(">", partial.end(0)) ++ if end < 0: ++ # ">" cannot be found, look for a word. ++ return re_notag.search(text, pos + 1) ++ else: ++ # "<" followed by a ">" was found -- fake a match. ++ end += 1 ++ return FakeMatch(text[partial.start(0) : end], end) ++ ++ ++class FakeMatch: ++ __slots__ = ["_text", "_end"] ++ ++ def end(self, group=0): ++ assert group == 0, "This specific object takes only group=0" ++ return self._end ++ ++ def __getitem__(self, group): ++ if group == 1: ++ return None ++ assert group == 0, "This specific object takes only group in {0,1}" ++ return self._text ++ ++ def __init__(self, text, end): ++ self._text, self._end = text, end ++ ++ ++# ----- End security-related performance workaround ----- ++ ++# Set up regular expressions. ++re_words = WordsRegex + re_chars = _lazy_re_compile(r"<[^>]+?>|(.)", re.S) + re_tag = _lazy_re_compile(r"<(/)?(\S+?)(?:(\s*/)|\s.*?)?>", re.S) + re_newlines = _lazy_re_compile(r"\r\n|\r") # Used in normalize_newlines +Index: Django-4.2.6/tests/utils_tests/test_text.py +=================================================================== +--- Django-4.2.6.orig/tests/utils_tests/test_text.py ++++ Django-4.2.6/tests/utils_tests/test_text.py +@@ -183,6 +183,32 @@ class TestUtilsText(SimpleTestCase): + truncator = text.Truncator("

I <3 python, what about you?

") + self.assertEqual("

I <3 python,…

", truncator.words(3, html=True)) + ++ # Only open brackets. ++ test = "<" * 60_000 ++ truncator = text.Truncator(test) ++ self.assertEqual(truncator.words(1, html=True), test) ++ ++ # Tags with special chars in attrs. ++ truncator = text.Truncator( ++ """Hello, my dear lady!""" ++ ) ++ self.assertEqual( ++ """Hello, my dear…""", ++ truncator.words(3, html=True), ++ ) ++ ++ # Tags with special non-latin chars in attrs. ++ truncator = text.Truncator("""

Hello, my dear lady!

""") ++ self.assertEqual( ++ """

Hello, my dear…

""", ++ truncator.words(3, html=True), ++ ) ++ ++ # Misplaced brackets. ++ truncator = text.Truncator("hello >< world") ++ self.assertEqual(truncator.words(1, html=True), "hello…") ++ self.assertEqual(truncator.words(2, html=True), "hello >< world") ++ + @patch("django.utils.text.Truncator.MAX_LENGTH_HTML", 10_000) + def test_truncate_words_html_size_limit(self): + max_len = text.Truncator.MAX_LENGTH_HTML diff --git a/python-Django.changes b/python-Django.changes index 9d4b489..4ff73c9 100644 --- a/python-Django.changes +++ b/python-Django.changes @@ -1,3 +1,8 @@ +------------------------------------------------------------------- +Thu Feb 29 13:19:00 UTC 2024 - Alberto Planas Dominguez + +- Add CVE-2024-27351.patch patch (CVE-2024-27351, bsc#1220358) + ------------------------------------------------------------------- Mon Oct 16 08:33:05 UTC 2023 - Daniel Garcia Moreno diff --git a/python-Django.spec b/python-Django.spec index 0b89689..f7d63bb 100644 --- a/python-Django.spec +++ b/python-Django.spec @@ -35,6 +35,8 @@ Source2: %{name}.keyring Source99: python-Django-rpmlintrc # PATCH-FIX-UPSTREAM https://github.com/django/django/commit/da2f8e8257d1bea4215381684ca4abfcee333c43 Refs #34118 -- Improved sanitize_address() error message for tuple with empty strings. Patch: sanitize_address.patch +# PATCH-FIX-UPSTREAM CVE-2024-27351.patch bsc#1220358 +Patch1: CVE-2024-27351.patch BuildRequires: %{python_module Jinja2 >= 2.9.2} BuildRequires: %{python_module Pillow >= 6.2.0} BuildRequires: %{python_module PyYAML}