From f6ad8c7676f85dfde5a279b6b1469251421289e2 Mon Sep 17 00:00:00 2001
From: Shai Berger
Date: Mon, 19 Feb 2024 13:56:37 +0100
Subject: [PATCH] Refs CVE-2024-27351 -- Forwardported release notes and tests.
Co-Authored-By: Mariusz Felisiak
---
docs/releases/3.2.25.txt | 8 ++++++++
docs/releases/4.2.11.txt | 8 ++++++++
docs/releases/5.0.3.txt | 8 ++++++++
tests/utils_tests/test_text.py | 27 +++++++++++++++++++++++++++
4 files changed, 51 insertions(+)
diff --git a/docs/releases/3.2.25.txt b/docs/releases/3.2.25.txt
index aa81c720d5..a3a90986ff 100644
--- a/docs/releases/3.2.25.txt
+++ b/docs/releases/3.2.25.txt
@@ -7,6 +7,14 @@ Django 3.2.25 release notes
Django 3.2.25 fixes a security issue with severity "moderate" and a regression
in 3.2.24.
+CVE-2024-27351: Potential regular expression denial-of-service in ``django.utils.text.Truncator.words()``
+=========================================================================================================
+
+``django.utils.text.Truncator.words()`` method (with ``html=True``) and
+:tfilter:`truncatewords_html` template filter were subject to a potential
+regular expression denial-of-service attack using a suitably crafted string
+(follow up to :cve:`2019-14232` and :cve:`2023-43665`).
+
Bugfixes
========
diff --git a/docs/releases/4.2.11.txt b/docs/releases/4.2.11.txt
index 82c691fcb7..c562e47866 100644
--- a/docs/releases/4.2.11.txt
+++ b/docs/releases/4.2.11.txt
@@ -7,6 +7,14 @@ Django 4.2.11 release notes
Django 4.2.11 fixes a security issue with severity "moderate" and a regression
in 4.2.10.
+CVE-2024-27351: Potential regular expression denial-of-service in ``django.utils.text.Truncator.words()``
+=========================================================================================================
+
+``django.utils.text.Truncator.words()`` method (with ``html=True``) and
+:tfilter:`truncatewords_html` template filter were subject to a potential
+regular expression denial-of-service attack using a suitably crafted string
+(follow up to :cve:`2019-14232` and :cve:`2023-43665`).
+
Bugfixes
========
diff --git a/docs/releases/5.0.3.txt b/docs/releases/5.0.3.txt
index 9db83d0135..bd3c6b5004 100644
--- a/docs/releases/5.0.3.txt
+++ b/docs/releases/5.0.3.txt
@@ -7,6 +7,14 @@ Django 5.0.3 release notes
Django 5.0.3 fixes a security issue with severity "moderate" and several bugs
in 5.0.2.
+CVE-2024-27351: Potential regular expression denial-of-service in ``django.utils.text.Truncator.words()``
+=========================================================================================================
+
+``django.utils.text.Truncator.words()`` method (with ``html=True``) and
+:tfilter:`truncatewords_html` template filter were subject to a potential
+regular expression denial-of-service attack using a suitably crafted string
+(follow up to :cve:`2019-14232` and :cve:`2023-43665`).
+
Bugfixes
========
diff --git a/tests/utils_tests/test_text.py b/tests/utils_tests/test_text.py
index b38d8238c5..ab2cfb3f7c 100644
--- a/tests/utils_tests/test_text.py
+++ b/tests/utils_tests/test_text.py
@@ -292,6 +292,33 @@ class TestUtilsText(SimpleTestCase):
truncator = text.Truncator("foo
")
self.assertEqual("foo", truncator.words(3, html=True))
+ # Only open brackets.
+ truncator = text.Truncator("<" * 60_000)
+ self.assertEqual(truncator.words(1, html=True), "<…")
+
+ # 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 >…")
+ self.assertEqual(truncator.words(3, html=True), "hello ><…")
+ self.assertEqual(truncator.words(4, 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