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:
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:
m = int(d) - d
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
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
========

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
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
========

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.00000000000000015, 16), "1.0000000000000002")
self.assertEqual(floatformat("1e199"), "1" + "0" * 199)
def test_invalid_inputs(self):
cases = [
@ -169,6 +170,22 @@ class FunctionTests(SimpleTestCase):
self.assertEqual(floatformat(pos_inf), "inf")
self.assertEqual(floatformat(neg_inf), "-inf")
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):
class FloatWrapper: