Fixed CVE-2019-6975 -- Fixed memory exhaustion in utils.numberformat.format().
Thanks Sjoerd Job Postmus for the report and initial patch. Thanks Michael Manfre, Tim Graham, and Florian Apolloner for review.
This commit is contained in:
parent
c901a1775b
commit
402c0caa85
|
@ -27,6 +27,19 @@ def format(number, decimal_sep, decimal_pos=None, grouping=0, thousand_sep='',
|
|||
# sign
|
||||
sign = ''
|
||||
if isinstance(number, Decimal):
|
||||
# Format values with more than 200 digits (an arbitrary cutoff) using
|
||||
# scientific notation to avoid high memory usage in {:f}'.format().
|
||||
_, digits, exponent = number.as_tuple()
|
||||
if abs(exponent) + len(digits) > 200:
|
||||
number = '{:e}'.format(number)
|
||||
coefficient, exponent = number.split('e')
|
||||
# Format the coefficient.
|
||||
coefficient = format(
|
||||
coefficient, decimal_sep, decimal_pos, grouping,
|
||||
thousand_sep, force_grouping, use_l10n,
|
||||
)
|
||||
return '{}e{}'.format(coefficient, exponent)
|
||||
else:
|
||||
str_number = '{:f}'.format(number)
|
||||
else:
|
||||
str_number = str(number)
|
||||
|
|
|
@ -5,3 +5,15 @@ Django 1.11.19 release notes
|
|||
*February 11, 2019*
|
||||
|
||||
Django 1.11.19 fixes a security issue in 1.11.18.
|
||||
|
||||
CVE-2019-6975: Memory exhaustion in ``django.utils.numberformat.format()``
|
||||
--------------------------------------------------------------------------
|
||||
|
||||
If ``django.utils.numberformat.format()`` -- used by ``contrib.admin`` as well
|
||||
as the the ``floatformat``, ``filesizeformat``, and ``intcomma`` templates
|
||||
filters -- received a ``Decimal`` with a large number of digits or a large
|
||||
exponent, it could lead to significant memory usage due to a call to
|
||||
``'{:f}'.format()``.
|
||||
|
||||
To avoid this, decimals with more than 200 digits are now formatted using
|
||||
scientific notation.
|
||||
|
|
|
@ -5,3 +5,15 @@ Django 2.0.11 release notes
|
|||
*February 11, 2019*
|
||||
|
||||
Django 2.0.11 fixes a security issue in 2.0.10.
|
||||
|
||||
CVE-2019-6975: Memory exhaustion in ``django.utils.numberformat.format()``
|
||||
--------------------------------------------------------------------------
|
||||
|
||||
If ``django.utils.numberformat.format()`` -- used by ``contrib.admin`` as well
|
||||
as the the ``floatformat``, ``filesizeformat``, and ``intcomma`` templates
|
||||
filters -- received a ``Decimal`` with a large number of digits or a large
|
||||
exponent, it could lead to significant memory usage due to a call to
|
||||
``'{:f}'.format()``.
|
||||
|
||||
To avoid this, decimals with more than 200 digits are now formatted using
|
||||
scientific notation.
|
||||
|
|
|
@ -6,6 +6,18 @@ Django 2.1.6 release notes
|
|||
|
||||
Django 2.1.6 fixes a security issue and a bug in 2.1.5.
|
||||
|
||||
CVE-2019-6975: Memory exhaustion in ``django.utils.numberformat.format()``
|
||||
--------------------------------------------------------------------------
|
||||
|
||||
If ``django.utils.numberformat.format()`` -- used by ``contrib.admin`` as well
|
||||
as the the ``floatformat``, ``filesizeformat``, and ``intcomma`` templates
|
||||
filters -- received a ``Decimal`` with a large number of digits or a large
|
||||
exponent, it could lead to significant memory usage due to a call to
|
||||
``'{:f}'.format()``.
|
||||
|
||||
To avoid this, decimals with more than 200 digits are now formatted using
|
||||
scientific notation.
|
||||
|
||||
Bugfixes
|
||||
========
|
||||
|
||||
|
|
|
@ -80,6 +80,25 @@ class TestNumberFormat(SimpleTestCase):
|
|||
)
|
||||
self.assertEqual(nformat(Decimal('3.'), '.'), '3')
|
||||
self.assertEqual(nformat(Decimal('3.0'), '.'), '3.0')
|
||||
# Very large & small numbers.
|
||||
tests = [
|
||||
('9e9999', None, '9e+9999'),
|
||||
('9e9999', 3, '9.000e+9999'),
|
||||
('9e201', None, '9e+201'),
|
||||
('9e200', None, '9e+200'),
|
||||
('1.2345e999', 2, '1.23e+999'),
|
||||
('9e-999', None, '9e-999'),
|
||||
('1e-7', 8, '0.00000010'),
|
||||
('1e-8', 8, '0.00000001'),
|
||||
('1e-9', 8, '0.00000000'),
|
||||
('1e-10', 8, '0.00000000'),
|
||||
('1e-11', 8, '0.00000000'),
|
||||
('1' + ('0' * 300), 3, '1.000e+300'),
|
||||
('0.{}1234'.format('0' * 299), 3, '1.234e-300'),
|
||||
]
|
||||
for value, decimal_pos, expected_value in tests:
|
||||
with self.subTest(value=value):
|
||||
self.assertEqual(nformat(Decimal(value), '.', decimal_pos), expected_value)
|
||||
|
||||
def test_decimal_subclass(self):
|
||||
class EuroDecimal(Decimal):
|
||||
|
|
Loading…
Reference in New Issue