new file mode 100644
@@ -0,0 +1,308 @@
+From ad866a1ca3e7d60da888d25d27e46a8adb2ed36e Mon Sep 17 00:00:00 2001
+From: Natalia <124304+nessita@users.noreply.github.com>
+Date: Mon, 6 Jan 2025 15:51:45 -0300
+Subject: [PATCH] Fixed CVE-2024-56374 -- Mitigated potential DoS in IPv6
+ validation.
+
+Thanks Saravana Kumar for the report, and Sarah Boyce and Mariusz
+Felisiak for the reviews.
+
+CVE: CVE-2024-56374
+
+Upstream-Status: Backport
+https://github.com/django/django/commit/ad866a1ca3e7d60da888d25d27e46a8adb2ed36e
+
+Signed-off-by: Natalia <124304+nessita@users.noreply.github.com>
+Co-authored-by: Natalia <124304+nessita@users.noreply.github.com>
+Signed-off-by: Saravanan <saravanan.kadambathursubramaniyam@windriver.com>
+---
+ django/db/models/fields/__init__.py | 4 +-
+ django/forms/fields.py | 7 +++-
+ django/utils/ipv6.py | 22 ++++++++--
+ docs/ref/forms/fields.txt | 13 +++++-
+ docs/releases/3.2.25.txt | 12 ++++++
+ .../field_tests/test_genericipaddressfield.py | 35 +++++++++++++++-
+ tests/utils_tests/test_ipv6.py | 40 +++++++++++++++++--
+ 7 files changed, 119 insertions(+), 14 deletions(-)
+
+diff --git a/django/db/models/fields/__init__.py b/django/db/models/fields/__init__.py
+index 167c3d2..148201d 100644
+--- a/django/db/models/fields/__init__.py
++++ b/django/db/models/fields/__init__.py
+@@ -22,7 +22,7 @@ from django.utils.dateparse import (
+ )
+ from django.utils.duration import duration_microseconds, duration_string
+ from django.utils.functional import Promise, cached_property
+-from django.utils.ipv6 import clean_ipv6_address
++from django.utils.ipv6 import MAX_IPV6_ADDRESS_LENGTH, clean_ipv6_address
+ from django.utils.itercompat import is_iterable
+ from django.utils.text import capfirst
+ from django.utils.translation import gettext_lazy as _
+@@ -1940,7 +1940,7 @@ class GenericIPAddressField(Field):
+ kwargs['unpack_ipv4'] = self.unpack_ipv4
+ if self.protocol != "both":
+ kwargs['protocol'] = self.protocol
+- if kwargs.get("max_length") == 39:
++ if kwargs.get("max_length") == self.max_length:
+ del kwargs['max_length']
+ return name, path, args, kwargs
+
+diff --git a/django/forms/fields.py b/django/forms/fields.py
+index 8adb09e..6969c4a 100644
+--- a/django/forms/fields.py
++++ b/django/forms/fields.py
+@@ -28,7 +28,7 @@ from django.forms.widgets import (
+ from django.utils import formats
+ from django.utils.dateparse import parse_datetime, parse_duration
+ from django.utils.duration import duration_string
+-from django.utils.ipv6 import clean_ipv6_address
++from django.utils.ipv6 import MAX_IPV6_ADDRESS_LENGTH, clean_ipv6_address
+ from django.utils.regex_helper import _lazy_re_compile
+ from django.utils.translation import gettext_lazy as _, ngettext_lazy
+
+@@ -1179,6 +1179,7 @@ class GenericIPAddressField(CharField):
+ def __init__(self, *, protocol='both', unpack_ipv4=False, **kwargs):
+ self.unpack_ipv4 = unpack_ipv4
+ self.default_validators = validators.ip_address_validators(protocol, unpack_ipv4)[0]
++ kwargs.setdefault("max_length", MAX_IPV6_ADDRESS_LENGTH)
+ super().__init__(**kwargs)
+
+ def to_python(self, value):
+@@ -1186,7 +1187,9 @@ class GenericIPAddressField(CharField):
+ return ''
+ value = value.strip()
+ if value and ':' in value:
+- return clean_ipv6_address(value, self.unpack_ipv4)
++ return clean_ipv6_address(
++ value, self.unpack_ipv4, max_length=self.max_length
++ )
+ return value
+
+
+diff --git a/django/utils/ipv6.py b/django/utils/ipv6.py
+index ddb8c80..aed7902 100644
+--- a/django/utils/ipv6.py
++++ b/django/utils/ipv6.py
+@@ -3,9 +3,23 @@ import ipaddress
+ from django.core.exceptions import ValidationError
+ from django.utils.translation import gettext_lazy as _
+
++MAX_IPV6_ADDRESS_LENGTH = 39
+
+-def clean_ipv6_address(ip_str, unpack_ipv4=False,
+- error_message=_("This is not a valid IPv6 address.")):
++
++def _ipv6_address_from_str(ip_str, max_length=MAX_IPV6_ADDRESS_LENGTH):
++ if len(ip_str) > max_length:
++ raise ValueError(
++ f"Unable to convert {ip_str} to an IPv6 address (value too long)."
++ )
++ return ipaddress.IPv6Address(int(ipaddress.IPv6Address(ip_str)))
++
++
++def clean_ipv6_address(
++ ip_str,
++ unpack_ipv4=False,
++ error_message=_("This is not a valid IPv6 address."),
++ max_length=MAX_IPV6_ADDRESS_LENGTH,
++ ):
+ """
+ Clean an IPv6 address string.
+
+@@ -23,7 +37,7 @@ def clean_ipv6_address(ip_str, unpack_ipv4=False,
+ Return a compressed IPv6 address or the same value.
+ """
+ try:
+- addr = ipaddress.IPv6Address(int(ipaddress.IPv6Address(ip_str)))
++ addr = _ipv6_address_from_str(ip_str, max_length)
+ except ValueError:
+ raise ValidationError(error_message, code='invalid')
+
+@@ -40,7 +54,7 @@ def is_valid_ipv6_address(ip_str):
+ Return whether or not the `ip_str` string is a valid IPv6 address.
+ """
+ try:
+- ipaddress.IPv6Address(ip_str)
++ _ipv6_address_from_str(ip_str)
+ except ValueError:
+ return False
+ return True
+diff --git a/docs/ref/forms/fields.txt b/docs/ref/forms/fields.txt
+index 5b485f2..45973eb 100644
+--- a/docs/ref/forms/fields.txt
++++ b/docs/ref/forms/fields.txt
+@@ -847,7 +847,7 @@ For each field, we describe the default widget used if you don't specify
+ * Empty value: ``''`` (an empty string)
+ * Normalizes to: A string. IPv6 addresses are normalized as described below.
+ * Validates that the given value is a valid IP address.
+- * Error message keys: ``required``, ``invalid``
++ * Error message keys: ``required``, ``invalid``, ``max_length``
+
+ The IPv6 address normalization follows :rfc:`4291#section-2.2` section 2.2,
+ including using the IPv4 format suggested in paragraph 3 of that section, like
+@@ -855,7 +855,7 @@ For each field, we describe the default widget used if you don't specify
+ ``2001::1``, and ``::ffff:0a0a:0a0a`` to ``::ffff:10.10.10.10``. All characters
+ are converted to lowercase.
+
+- Takes two optional arguments:
++ Takes three optional arguments:
+
+ .. attribute:: protocol
+
+@@ -870,6 +870,15 @@ For each field, we describe the default widget used if you don't specify
+ ``192.0.2.1``. Default is disabled. Can only be used
+ when ``protocol`` is set to ``'both'``.
+
++ .. attribute:: max_length
++
++ Defaults to 39, and behaves the same way as it does for
++ :class:`CharField`.
++
++ .. versionchanged:: 4.2.18
++
++ The default value for ``max_length`` was set to 39 characters.
++
+ ``MultipleChoiceField``
+ -----------------------
+
+diff --git a/docs/releases/3.2.25.txt b/docs/releases/3.2.25.txt
+index f8d9ce2..93ab341 100644
+--- a/docs/releases/3.2.25.txt
++++ b/docs/releases/3.2.25.txt
+@@ -21,6 +21,18 @@ CVE-2025-26699: Potential denial-of-service vulnerability in ``django.utils.text
+ The ``wrap()`` and :tfilter:`wordwrap` template filter were subject to a
+ potential denial-of-service attack when used with very long strings.
+
++CVE-2024-56374: Potential denial-of-service vulnerability in IPv6 validation
++============================================================================
++
++Lack of upper bound limit enforcement in strings passed when performing IPv6
++validation could lead to a potential denial-of-service attack. The undocumented
++and private functions ``clean_ipv6_address`` and ``is_valid_ipv6_address`` were
++vulnerable, as was the :class:`django.forms.GenericIPAddressField` form field,
++which has now been updated to define a ``max_length`` of 39 characters.
++
++The :class:`django.db.models.GenericIPAddressField` model field was not
++affected.
++
+ Bugfixes
+ ========
+
+diff --git a/tests/forms_tests/field_tests/test_genericipaddressfield.py b/tests/forms_tests/field_tests/test_genericipaddressfield.py
+index 92dbd71..fc3f129 100644
+--- a/tests/forms_tests/field_tests/test_genericipaddressfield.py
++++ b/tests/forms_tests/field_tests/test_genericipaddressfield.py
+@@ -1,6 +1,7 @@
+ from django.core.exceptions import ValidationError
+ from django.forms import GenericIPAddressField
+ from django.test import SimpleTestCase
++from django.utils.ipv6 import MAX_IPV6_ADDRESS_LENGTH
+
+
+ class GenericIPAddressFieldTest(SimpleTestCase):
+@@ -90,6 +91,35 @@ class GenericIPAddressFieldTest(SimpleTestCase):
+ with self.assertRaisesMessage(ValidationError, "'This is not a valid IPv6 address.'"):
+ f.clean('1:2')
+
++ def test_generic_ipaddress_max_length_custom(self):
++ # Valid IPv4-mapped IPv6 address, len 45.
++ addr = "0000:0000:0000:0000:0000:ffff:192.168.100.228"
++ f = GenericIPAddressField(max_length=len(addr))
++ f.clean(addr)
++
++ def test_generic_ipaddress_max_length_validation_error(self):
++ # Valid IPv4-mapped IPv6 address, len 45.
++ addr = "0000:0000:0000:0000:0000:ffff:192.168.100.228"
++
++ cases = [
++ ({}, MAX_IPV6_ADDRESS_LENGTH), # Default value.
++ ({"max_length": len(addr) - 1}, len(addr) - 1),
++ ]
++ for kwargs, max_length in cases:
++ max_length_plus_one = max_length + 1
++ msg = (
++ f"Ensure this value has at most {max_length} characters (it has "
++ f"{max_length_plus_one}).'"
++ )
++ with self.subTest(max_length=max_length):
++ f = GenericIPAddressField(**kwargs)
++ with self.assertRaisesMessage(ValidationError, msg):
++ f.clean("x" * max_length_plus_one)
++ with self.assertRaisesMessage(
++ ValidationError, "This is not a valid IPv6 address."
++ ):
++ f.clean(addr)
++
+ def test_generic_ipaddress_as_generic_not_required(self):
+ f = GenericIPAddressField(required=False)
+ self.assertEqual(f.clean(''), '')
+@@ -104,7 +134,10 @@ class GenericIPAddressFieldTest(SimpleTestCase):
+ with self.assertRaisesMessage(ValidationError, "'Enter a valid IPv4 or IPv6 address.'"):
+ f.clean('256.125.1.5')
+ self.assertEqual(f.clean(' fe80::223:6cff:fe8a:2e8a '), 'fe80::223:6cff:fe8a:2e8a')
+- self.assertEqual(f.clean(' 2a02::223:6cff:fe8a:2e8a '), '2a02::223:6cff:fe8a:2e8a')
++ self.assertEqual(
++ f.clean(" " * MAX_IPV6_ADDRESS_LENGTH + " 2a02::223:6cff:fe8a:2e8a "),
++ "2a02::223:6cff:fe8a:2e8a",
++ )
+ with self.assertRaisesMessage(ValidationError, "'This is not a valid IPv6 address.'"):
+ f.clean('12345:2:3:4')
+ with self.assertRaisesMessage(ValidationError, "'This is not a valid IPv6 address.'"):
+diff --git a/tests/utils_tests/test_ipv6.py b/tests/utils_tests/test_ipv6.py
+index 4e434f3..1ac6763 100644
+--- a/tests/utils_tests/test_ipv6.py
++++ b/tests/utils_tests/test_ipv6.py
+@@ -1,9 +1,17 @@
+-import unittest
++import traceback
++from io import StringIO
+
+-from django.utils.ipv6 import clean_ipv6_address, is_valid_ipv6_address
++from django.core.exceptions import ValidationError
++from django.test import SimpleTestCase
++from django.utils.ipv6 import (
++ MAX_IPV6_ADDRESS_LENGTH,
++ clean_ipv6_address,
++ is_valid_ipv6_address,
++)
++from django.utils.version import PY310
+
+
+-class TestUtilsIPv6(unittest.TestCase):
++class TestUtilsIPv6(SimpleTestCase):
+
+ def test_validates_correct_plain_address(self):
+ self.assertTrue(is_valid_ipv6_address('fe80::223:6cff:fe8a:2e8a'))
+@@ -55,3 +63,29 @@ class TestUtilsIPv6(unittest.TestCase):
+ self.assertEqual(clean_ipv6_address('::ffff:0a0a:0a0a', unpack_ipv4=True), '10.10.10.10')
+ self.assertEqual(clean_ipv6_address('::ffff:1234:1234', unpack_ipv4=True), '18.52.18.52')
+ self.assertEqual(clean_ipv6_address('::ffff:18.52.18.52', unpack_ipv4=True), '18.52.18.52')
++
++ def test_address_too_long(self):
++ addresses = [
++ "0000:0000:0000:0000:0000:ffff:192.168.100.228", # IPv4-mapped IPv6 address
++ "0000:0000:0000:0000:0000:ffff:192.168.100.228%123456", # % scope/zone
++ "fe80::223:6cff:fe8a:2e8a:1234:5678:00000", # MAX_IPV6_ADDRESS_LENGTH + 1
++ ]
++ msg = "This is the error message."
++ value_error_msg = "Unable to convert %s to an IPv6 address (value too long)."
++ for addr in addresses:
++ with self.subTest(addr=addr):
++ self.assertGreater(len(addr), MAX_IPV6_ADDRESS_LENGTH)
++ self.assertEqual(is_valid_ipv6_address(addr), False)
++ with self.assertRaisesMessage(ValidationError, msg) as ctx:
++ clean_ipv6_address(addr, error_message=msg)
++ exception_traceback = StringIO()
++ if PY310:
++ traceback.print_exception(ctx.exception, file=exception_traceback)
++ else:
++ traceback.print_exception(
++ type(ctx.exception),
++ value=ctx.exception,
++ tb=ctx.exception.__traceback__,
++ file=exception_traceback,
++ )
++ self.assertIn(value_error_msg % addr, exception_traceback.getvalue())
+--
+2.40.0
+
new file mode 100644
@@ -0,0 +1,315 @@
+From ad866a1ca3e7d60da888d25d27e46a8adb2ed36e Mon Sep 17 00:00:00 2001
+From: Natalia <124304+nessita@users.noreply.github.com>
+Date: Mon, 6 Jan 2025 15:51:45 -0300
+Subject: [PATCH] Fixed CVE-2024-56374 -- Mitigated potential DoS in IPv6
+ validation.
+
+Thanks Saravana Kumar for the report, and Sarah Boyce and Mariusz
+Felisiak for the reviews.
+
+CVE: CVE-2024-56374
+
+Upstream-Status: Backport
+https://github.com/django/django/commit/ad866a1ca3e7d60da888d25d27e46a8adb2ed36e
+
+Signed-off-by: Natalia <124304+nessita@users.noreply.github.com>
+Co-authored-by: Natalia <124304+nessita@users.noreply.github.com>
+Signed-off-by: Saravanan <saravanan.kadambathursubramaniyam@windriver.com>
+
+%% original patch: CVE-2024-56374.patch
+---
+ django/db/models/fields/__init__.py | 6 +--
+ django/forms/fields.py | 7 +++-
+ django/utils/ipv6.py | 22 ++++++++--
+ docs/ref/forms/fields.txt | 13 +++++-
+ docs/releases/2.2.28.txt | 12 ++++++
+ .../field_tests/test_genericipaddressfield.py | 35 +++++++++++++++-
+ tests/utils_tests/test_ipv6.py | 40 +++++++++++++++++--
+ 7 files changed, 120 insertions(+), 15 deletions(-)
+
+diff --git a/django/db/models/fields/__init__.py b/django/db/models/fields/__init__.py
+index e2d1846..c77702f 100644
+--- a/django/db/models/fields/__init__.py
++++ b/django/db/models/fields/__init__.py
+@@ -26,7 +26,7 @@ from django.utils.dateparse import (
+ )
+ from django.utils.duration import duration_microseconds, duration_string
+ from django.utils.functional import Promise, cached_property
+-from django.utils.ipv6 import clean_ipv6_address
++from django.utils.ipv6 import MAX_IPV6_ADDRESS_LENGTH, clean_ipv6_address
+ from django.utils.itercompat import is_iterable
+ from django.utils.text import capfirst
+ from django.utils.translation import gettext_lazy as _
+@@ -1904,7 +1904,7 @@ class GenericIPAddressField(Field):
+ self.default_validators, invalid_error_message = \
+ validators.ip_address_validators(protocol, unpack_ipv4)
+ self.default_error_messages['invalid'] = invalid_error_message
+- kwargs['max_length'] = 39
++ kwargs["max_length"] = MAX_IPV6_ADDRESS_LENGTH
+ super().__init__(verbose_name, name, *args, **kwargs)
+
+ def check(self, **kwargs):
+@@ -1931,7 +1931,7 @@ class GenericIPAddressField(Field):
+ kwargs['unpack_ipv4'] = self.unpack_ipv4
+ if self.protocol != "both":
+ kwargs['protocol'] = self.protocol
+- if kwargs.get("max_length") == 39:
++ if kwargs.get("max_length") == self.max_length:
+ del kwargs['max_length']
+ return name, path, args, kwargs
+
+diff --git a/django/forms/fields.py b/django/forms/fields.py
+index f939338..b3156b9 100644
+--- a/django/forms/fields.py
++++ b/django/forms/fields.py
+@@ -29,7 +29,7 @@ from django.forms.widgets import (
+ from django.utils import formats
+ from django.utils.dateparse import parse_duration
+ from django.utils.duration import duration_string
+-from django.utils.ipv6 import clean_ipv6_address
++from django.utils.ipv6 import MAX_IPV6_ADDRESS_LENGTH, clean_ipv6_address
+ from django.utils.translation import gettext_lazy as _, ngettext_lazy
+
+ __all__ = (
+@@ -1162,6 +1162,7 @@ class GenericIPAddressField(CharField):
+ def __init__(self, *, protocol='both', unpack_ipv4=False, **kwargs):
+ self.unpack_ipv4 = unpack_ipv4
+ self.default_validators = validators.ip_address_validators(protocol, unpack_ipv4)[0]
++ kwargs.setdefault("max_length", MAX_IPV6_ADDRESS_LENGTH)
+ super().__init__(**kwargs)
+
+ def to_python(self, value):
+@@ -1169,7 +1170,9 @@ class GenericIPAddressField(CharField):
+ return ''
+ value = value.strip()
+ if value and ':' in value:
+- return clean_ipv6_address(value, self.unpack_ipv4)
++ return clean_ipv6_address(
++ value, self.unpack_ipv4, max_length=self.max_length
++ )
+ return value
+
+
+diff --git a/django/utils/ipv6.py b/django/utils/ipv6.py
+index ddb8c80..aed7902 100644
+--- a/django/utils/ipv6.py
++++ b/django/utils/ipv6.py
+@@ -3,9 +3,23 @@ import ipaddress
+ from django.core.exceptions import ValidationError
+ from django.utils.translation import gettext_lazy as _
+
++MAX_IPV6_ADDRESS_LENGTH = 39
+
+-def clean_ipv6_address(ip_str, unpack_ipv4=False,
+- error_message=_("This is not a valid IPv6 address.")):
++
++def _ipv6_address_from_str(ip_str, max_length=MAX_IPV6_ADDRESS_LENGTH):
++ if len(ip_str) > max_length:
++ raise ValueError(
++ f"Unable to convert {ip_str} to an IPv6 address (value too long)."
++ )
++ return ipaddress.IPv6Address(int(ipaddress.IPv6Address(ip_str)))
++
++
++def clean_ipv6_address(
++ ip_str,
++ unpack_ipv4=False,
++ error_message=_("This is not a valid IPv6 address."),
++ max_length=MAX_IPV6_ADDRESS_LENGTH,
++ ):
+ """
+ Clean an IPv6 address string.
+
+@@ -23,7 +37,7 @@ def clean_ipv6_address(ip_str, unpack_ipv4=False,
+ Return a compressed IPv6 address or the same value.
+ """
+ try:
+- addr = ipaddress.IPv6Address(int(ipaddress.IPv6Address(ip_str)))
++ addr = _ipv6_address_from_str(ip_str, max_length)
+ except ValueError:
+ raise ValidationError(error_message, code='invalid')
+
+@@ -40,7 +54,7 @@ def is_valid_ipv6_address(ip_str):
+ Return whether or not the `ip_str` string is a valid IPv6 address.
+ """
+ try:
+- ipaddress.IPv6Address(ip_str)
++ _ipv6_address_from_str(ip_str)
+ except ValueError:
+ return False
+ return True
+diff --git a/docs/ref/forms/fields.txt b/docs/ref/forms/fields.txt
+index 3a888ef..688890a 100644
+--- a/docs/ref/forms/fields.txt
++++ b/docs/ref/forms/fields.txt
+@@ -791,7 +791,7 @@ For each field, we describe the default widget used if you don't specify
+ * Empty value: ``''`` (an empty string)
+ * Normalizes to: A string. IPv6 addresses are normalized as described below.
+ * Validates that the given value is a valid IP address.
+- * Error message keys: ``required``, ``invalid``
++ * Error message keys: ``required``, ``invalid``, ``max_length``
+
+ The IPv6 address normalization follows :rfc:`4291#section-2.2` section 2.2,
+ including using the IPv4 format suggested in paragraph 3 of that section, like
+@@ -799,7 +799,7 @@ For each field, we describe the default widget used if you don't specify
+ ``2001::1``, and ``::ffff:0a0a:0a0a`` to ``::ffff:10.10.10.10``. All characters
+ are converted to lowercase.
+
+- Takes two optional arguments:
++ Takes three optional arguments:
+
+ .. attribute:: protocol
+
+@@ -814,6 +814,15 @@ For each field, we describe the default widget used if you don't specify
+ ``192.0.2.1``. Default is disabled. Can only be used
+ when ``protocol`` is set to ``'both'``.
+
++ .. attribute:: max_length
++
++ Defaults to 39, and behaves the same way as it does for
++ :class:`CharField`.
++
++ .. versionchanged:: 4.2.18
++
++ The default value for ``max_length`` was set to 39 characters.
++
+ ``MultipleChoiceField``
+ -----------------------
+
+diff --git a/docs/releases/2.2.28.txt b/docs/releases/2.2.28.txt
+index 7096d13..0e092f0 100644
+--- a/docs/releases/2.2.28.txt
++++ b/docs/releases/2.2.28.txt
+@@ -105,3 +105,15 @@ CVE-2025-26699: Potential denial-of-service vulnerability in ``django.utils.text
+ The ``wrap()`` and :tfilter:`wordwrap` template filter were subject to a
+ potential denial-of-service attack when used with very long strings.
+
++CVE-2024-56374: Potential denial-of-service vulnerability in IPv6 validation
++============================================================================
++
++Lack of upper bound limit enforcement in strings passed when performing IPv6
++validation could lead to a potential denial-of-service attack. The undocumented
++and private functions ``clean_ipv6_address`` and ``is_valid_ipv6_address`` were
++vulnerable, as was the :class:`django.forms.GenericIPAddressField` form field,
++which has now been updated to define a ``max_length`` of 39 characters.
++
++The :class:`django.db.models.GenericIPAddressField` model field was not
++affected.
++
+diff --git a/tests/forms_tests/field_tests/test_genericipaddressfield.py b/tests/forms_tests/field_tests/test_genericipaddressfield.py
+index 97a83e3..4c79d78 100644
+--- a/tests/forms_tests/field_tests/test_genericipaddressfield.py
++++ b/tests/forms_tests/field_tests/test_genericipaddressfield.py
+@@ -1,5 +1,6 @@
+ from django.forms import GenericIPAddressField, ValidationError
+ from django.test import SimpleTestCase
++from django.utils.ipv6 import MAX_IPV6_ADDRESS_LENGTH
+
+
+ class GenericIPAddressFieldTest(SimpleTestCase):
+@@ -89,6 +90,35 @@ class GenericIPAddressFieldTest(SimpleTestCase):
+ with self.assertRaisesMessage(ValidationError, "'This is not a valid IPv6 address.'"):
+ f.clean('1:2')
+
++ def test_generic_ipaddress_max_length_custom(self):
++ # Valid IPv4-mapped IPv6 address, len 45.
++ addr = "0000:0000:0000:0000:0000:ffff:192.168.100.228"
++ f = GenericIPAddressField(max_length=len(addr))
++ f.clean(addr)
++
++ def test_generic_ipaddress_max_length_validation_error(self):
++ # Valid IPv4-mapped IPv6 address, len 45.
++ addr = "0000:0000:0000:0000:0000:ffff:192.168.100.228"
++
++ cases = [
++ ({}, MAX_IPV6_ADDRESS_LENGTH), # Default value.
++ ({"max_length": len(addr) - 1}, len(addr) - 1),
++ ]
++ for kwargs, max_length in cases:
++ max_length_plus_one = max_length + 1
++ msg = (
++ f"Ensure this value has at most {max_length} characters (it has "
++ f"{max_length_plus_one}).'"
++ )
++ with self.subTest(max_length=max_length):
++ f = GenericIPAddressField(**kwargs)
++ with self.assertRaisesMessage(ValidationError, msg):
++ f.clean("x" * max_length_plus_one)
++ with self.assertRaisesMessage(
++ ValidationError, "This is not a valid IPv6 address."
++ ):
++ f.clean(addr)
++
+ def test_generic_ipaddress_as_generic_not_required(self):
+ f = GenericIPAddressField(required=False)
+ self.assertEqual(f.clean(''), '')
+@@ -103,7 +133,10 @@ class GenericIPAddressFieldTest(SimpleTestCase):
+ with self.assertRaisesMessage(ValidationError, "'Enter a valid IPv4 or IPv6 address.'"):
+ f.clean('256.125.1.5')
+ self.assertEqual(f.clean(' fe80::223:6cff:fe8a:2e8a '), 'fe80::223:6cff:fe8a:2e8a')
+- self.assertEqual(f.clean(' 2a02::223:6cff:fe8a:2e8a '), '2a02::223:6cff:fe8a:2e8a')
++ self.assertEqual(
++ f.clean(" " * MAX_IPV6_ADDRESS_LENGTH + " 2a02::223:6cff:fe8a:2e8a "),
++ "2a02::223:6cff:fe8a:2e8a",
++ )
+ with self.assertRaisesMessage(ValidationError, "'This is not a valid IPv6 address.'"):
+ f.clean('12345:2:3:4')
+ with self.assertRaisesMessage(ValidationError, "'This is not a valid IPv6 address.'"):
+diff --git a/tests/utils_tests/test_ipv6.py b/tests/utils_tests/test_ipv6.py
+index 4e434f3..1ac6763 100644
+--- a/tests/utils_tests/test_ipv6.py
++++ b/tests/utils_tests/test_ipv6.py
+@@ -1,9 +1,17 @@
+-import unittest
++import traceback
++from io import StringIO
+
+-from django.utils.ipv6 import clean_ipv6_address, is_valid_ipv6_address
++from django.core.exceptions import ValidationError
++from django.test import SimpleTestCase
++from django.utils.ipv6 import (
++ MAX_IPV6_ADDRESS_LENGTH,
++ clean_ipv6_address,
++ is_valid_ipv6_address,
++)
++from django.utils.version import PY310
+
+
+-class TestUtilsIPv6(unittest.TestCase):
++class TestUtilsIPv6(SimpleTestCase):
+
+ def test_validates_correct_plain_address(self):
+ self.assertTrue(is_valid_ipv6_address('fe80::223:6cff:fe8a:2e8a'))
+@@ -55,3 +63,29 @@ class TestUtilsIPv6(unittest.TestCase):
+ self.assertEqual(clean_ipv6_address('::ffff:0a0a:0a0a', unpack_ipv4=True), '10.10.10.10')
+ self.assertEqual(clean_ipv6_address('::ffff:1234:1234', unpack_ipv4=True), '18.52.18.52')
+ self.assertEqual(clean_ipv6_address('::ffff:18.52.18.52', unpack_ipv4=True), '18.52.18.52')
++
++ def test_address_too_long(self):
++ addresses = [
++ "0000:0000:0000:0000:0000:ffff:192.168.100.228", # IPv4-mapped IPv6 address
++ "0000:0000:0000:0000:0000:ffff:192.168.100.228%123456", # % scope/zone
++ "fe80::223:6cff:fe8a:2e8a:1234:5678:00000", # MAX_IPV6_ADDRESS_LENGTH + 1
++ ]
++ msg = "This is the error message."
++ value_error_msg = "Unable to convert %s to an IPv6 address (value too long)."
++ for addr in addresses:
++ with self.subTest(addr=addr):
++ self.assertGreater(len(addr), MAX_IPV6_ADDRESS_LENGTH)
++ self.assertEqual(is_valid_ipv6_address(addr), False)
++ with self.assertRaisesMessage(ValidationError, msg) as ctx:
++ clean_ipv6_address(addr, error_message=msg)
++ exception_traceback = StringIO()
++ if PY310:
++ traceback.print_exception(ctx.exception, file=exception_traceback)
++ else:
++ traceback.print_exception(
++ type(ctx.exception),
++ value=ctx.exception,
++ tb=ctx.exception.__traceback__,
++ file=exception_traceback,
++ )
++ self.assertIn(value_error_msg % addr, exception_traceback.getvalue())
+--
+2.40.0
+
@@ -26,6 +26,7 @@ SRC_URI += "file://CVE-2023-31047.patch \
file://CVE-2024-53907.patch \
file://CVE-2024-27351.patch \
file://CVE-2025-26699.patch \
+ file://CVE-2024-56374.patch \
"
SRC_URI[sha256sum] = "0200b657afbf1bc08003845ddda053c7641b9b24951e52acd51f6abda33a7413"
@@ -8,6 +8,7 @@ RDEPENDS:${PN} += "\
"
SRC_URI += "\
file://CVE-2025-26699.patch \
+ file://CVE-2024-56374.patch \
"
# Set DEFAULT_PREFERENCE so that the LTS version of django is built by
Reference: https://nvd.nist.gov/vuln/detail/CVE-2024-56374 Upstream-patch: https://github.com/django/django/commit/ad866a1ca3e7d60da888d25d27e46a8adb2ed36e Signed-off-by: Saravanan <saravanan.kadambathursubramaniyam@windriver.com> --- .../CVE-2024-56374.patch | 308 +++++++++++++++++ .../python3-django/CVE-2024-56374.patch | 315 ++++++++++++++++++ .../python/python3-django_2.2.28.bb | 1 + .../python/python3-django_3.2.25.bb | 1 + 4 files changed, 625 insertions(+) create mode 100644 meta-python/recipes-devtools/python/python3-django-3.2.25/CVE-2024-56374.patch create mode 100644 meta-python/recipes-devtools/python/python3-django/CVE-2024-56374.patch