1
0
mirror of https://github.com/django/django.git synced 2025-06-05 19:49:13 +00:00

Fixed CVE-2024-41989 -- Prevented excessive memory consumption in floatformat.

Thanks Elias Myllymäki for the report.

Co-authored-by: Shai Berger <shai@platonix.com>
This commit is contained in:
Sarah Boyce 2024-07-12 11:38:34 +02:00
parent 8deb6bb1fc
commit c19465ad87
4 changed files with 48 additions and 0 deletions

View File

@ -162,6 +162,19 @@ def floatformat(text, arg=-1):
except ValueError: except ValueError:
return input_val return input_val
_, digits, exponent = d.as_tuple()
try:
number_of_digits_and_exponent_sum = len(digits) + abs(exponent)
except TypeError:
# Exponent values can be "F", "n", "N".
number_of_digits_and_exponent_sum = 0
# Values with more than 200 digits, or with a large exponent, are returned "as is"
# to avoid high memory consumption and potential denial-of-service attacks.
# The cut-off of 200 is consistent with django.utils.numberformat.floatformat().
if number_of_digits_and_exponent_sum > 200:
return input_val
try: try:
m = int(d) - d m = int(d) - d
except (ValueError, OverflowError, InvalidOperation): except (ValueError, OverflowError, InvalidOperation):

View File

@ -7,6 +7,15 @@ Django 4.2.15 release notes
Django 4.2.15 fixes three security issues with severity "moderate", one Django 4.2.15 fixes three security issues with severity "moderate", one
security issue with severity "high", and a regression in 4.2.14. security issue with severity "high", and a regression in 4.2.14.
CVE-2024-41989: Memory exhaustion in ``django.utils.numberformat.floatformat()``
================================================================================
If :tfilter:`floatformat` received a string representation of a number in
scientific notation with a large exponent, it could lead to significant memory
consumption.
To avoid this, decimals with more than 200 digits are now returned as is.
Bugfixes Bugfixes
======== ========

View File

@ -7,6 +7,15 @@ Django 5.0.8 release notes
Django 5.0.8 fixes three security issues with severity "moderate", one security Django 5.0.8 fixes three security issues with severity "moderate", one security
issue with severity "high", and several bugs in 5.0.7. issue with severity "high", and several bugs in 5.0.7.
CVE-2024-41989: Memory exhaustion in ``django.utils.numberformat.floatformat()``
================================================================================
If :tfilter:`floatformat` received a string representation of a number in
scientific notation with a large exponent, it could lead to significant memory
consumption.
To avoid this, decimals with more than 200 digits are now returned as is.
Bugfixes Bugfixes
======== ========

View File

@ -73,6 +73,7 @@ class FunctionTests(SimpleTestCase):
self.assertEqual(floatformat(1.5e-15, 20), "0.00000000000000150000") self.assertEqual(floatformat(1.5e-15, 20), "0.00000000000000150000")
self.assertEqual(floatformat(1.5e-15, -20), "0.00000000000000150000") self.assertEqual(floatformat(1.5e-15, -20), "0.00000000000000150000")
self.assertEqual(floatformat(1.00000000000000015, 16), "1.0000000000000002") self.assertEqual(floatformat(1.00000000000000015, 16), "1.0000000000000002")
self.assertEqual(floatformat("1e199"), "1" + "0" * 199)
def test_invalid_inputs(self): def test_invalid_inputs(self):
cases = [ cases = [
@ -169,6 +170,22 @@ class FunctionTests(SimpleTestCase):
self.assertEqual(floatformat(pos_inf), "inf") self.assertEqual(floatformat(pos_inf), "inf")
self.assertEqual(floatformat(neg_inf), "-inf") self.assertEqual(floatformat(neg_inf), "-inf")
self.assertEqual(floatformat(pos_inf / pos_inf), "nan") self.assertEqual(floatformat(pos_inf / pos_inf), "nan")
self.assertEqual(floatformat("inf"), "inf")
self.assertEqual(floatformat("NaN"), "NaN")
def test_too_many_digits_to_render(self):
cases = [
"1e200",
"1E200",
"1E10000000000000000",
"-1E10000000000000000",
"1e10000000000000000",
"-1e10000000000000000",
"1" + "0" * 1_000_000,
]
for value in cases:
with self.subTest(value=value):
self.assertEqual(floatformat(value), value)
def test_float_dunder_method(self): def test_float_dunder_method(self):
class FloatWrapper: class FloatWrapper: