Skip to content

Commit 27900fe

Browse files
sarahboyceshaib
andcommitted
[5.0.x] Fixed CVE-2024-41989 -- Prevented excessive memory consumption in floatformat.
Thanks Elias Myllymäki for the report. Co-authored-by: Shai Berger <[email protected]>
1 parent d7f9554 commit 27900fe

File tree

4 files changed

+48
-0
lines changed

4 files changed

+48
-0
lines changed

django/template/defaultfilters.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,19 @@ def floatformat(text, arg=-1):
164164
except ValueError:
165165
return input_val
166166

167+
_, digits, exponent = d.as_tuple()
168+
try:
169+
number_of_digits_and_exponent_sum = len(digits) + abs(exponent)
170+
except TypeError:
171+
# Exponent values can be "F", "n", "N".
172+
number_of_digits_and_exponent_sum = 0
173+
174+
# Values with more than 200 digits, or with a large exponent, are returned "as is"
175+
# to avoid high memory consumption and potential denial-of-service attacks.
176+
# The cut-off of 200 is consistent with django.utils.numberformat.floatformat().
177+
if number_of_digits_and_exponent_sum > 200:
178+
return input_val
179+
167180
try:
168181
m = int(d) - d
169182
except (ValueError, OverflowError, InvalidOperation):

docs/releases/4.2.15.txt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,15 @@ Django 4.2.15 release notes
77
Django 4.2.15 fixes three security issues with severity "moderate", one
88
security issue with severity "high", and a regression in 4.2.14.
99

10+
CVE-2024-41989: Memory exhaustion in ``django.utils.numberformat.floatformat()``
11+
================================================================================
12+
13+
If :tfilter:`floatformat` received a string representation of a number in
14+
scientific notation with a large exponent, it could lead to significant memory
15+
consumption.
16+
17+
To avoid this, decimals with more than 200 digits are now returned as is.
18+
1019
Bugfixes
1120
========
1221

docs/releases/5.0.8.txt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,15 @@ Django 5.0.8 release notes
77
Django 5.0.8 fixes three security issues with severity "moderate", one security
88
issue with severity "high", and several bugs in 5.0.7.
99

10+
CVE-2024-41989: Memory exhaustion in ``django.utils.numberformat.floatformat()``
11+
================================================================================
12+
13+
If :tfilter:`floatformat` received a string representation of a number in
14+
scientific notation with a large exponent, it could lead to significant memory
15+
consumption.
16+
17+
To avoid this, decimals with more than 200 digits are now returned as is.
18+
1019
Bugfixes
1120
========
1221

tests/template_tests/filter_tests/test_floatformat.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ def test_inputs(self):
7777
self.assertEqual(floatformat(1.5e-15, 20), "0.00000000000000150000")
7878
self.assertEqual(floatformat(1.5e-15, -20), "0.00000000000000150000")
7979
self.assertEqual(floatformat(1.00000000000000015, 16), "1.0000000000000002")
80+
self.assertEqual(floatformat("1e199"), "1" + "0" * 199)
8081

8182
def test_force_grouping(self):
8283
with translation.override("en"):
@@ -134,6 +135,22 @@ def test_infinity(self):
134135
self.assertEqual(floatformat(pos_inf), "inf")
135136
self.assertEqual(floatformat(neg_inf), "-inf")
136137
self.assertEqual(floatformat(pos_inf / pos_inf), "nan")
138+
self.assertEqual(floatformat("inf"), "inf")
139+
self.assertEqual(floatformat("NaN"), "NaN")
140+
141+
def test_too_many_digits_to_render(self):
142+
cases = [
143+
"1e200",
144+
"1E200",
145+
"1E10000000000000000",
146+
"-1E10000000000000000",
147+
"1e10000000000000000",
148+
"-1e10000000000000000",
149+
"1" + "0" * 1_000_000,
150+
]
151+
for value in cases:
152+
with self.subTest(value=value):
153+
self.assertEqual(floatformat(value), value)
137154

138155
def test_float_dunder_method(self):
139156
class FloatWrapper:

0 commit comments

Comments
 (0)