diff --git a/debian/changelog b/debian/changelog index fa89c8b21..55d1fc21b 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,10 @@ +python-django (1:1.10.7-2+deb9u5) stretch-security; urgency=high + + * CVE-2019-6975: Fix memory exhaustion in utils.numberformat.format(). + (Closes: #922027) + + -- Chris Lamb Mon, 11 Feb 2019 15:01:30 +0100 + python-django (1:1.10.7-2+deb9u4) stretch-security; urgency=high * CVE-2019-3498: Prevent a content-spoofing vulnerability in the default diff --git a/debian/patches/0019-CVE-2019-6795.patch b/debian/patches/0019-CVE-2019-6795.patch new file mode 100644 index 000000000..39c2f864c --- /dev/null +++ b/debian/patches/0019-CVE-2019-6795.patch @@ -0,0 +1,69 @@ +From: Carlton Gibson +Date: Mon, 11 Feb 2019 11:15:45 +0100 +Subject: 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. + +Backport of 402c0caa851e265410fbcaa55318f22d2bf22ee2 from master. +--- + django/utils/numberformat.py | 15 ++++++++++++++- + tests/utils_tests/test_numberformat.py | 18 ++++++++++++++++++ + 2 files changed, 32 insertions(+), 1 deletion(-) + +diff --git a/django/utils/numberformat.py b/django/utils/numberformat.py +index 6667d82..8b4d228 100644 +--- a/django/utils/numberformat.py ++++ b/django/utils/numberformat.py +@@ -27,7 +27,20 @@ def format(number, decimal_sep, decimal_pos=None, grouping=0, thousand_sep='', + # sign + sign = '' + if isinstance(number, Decimal): +- str_number = '{:f}'.format(number) ++ # 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, ++ ) ++ return '{}e{}'.format(coefficient, exponent) ++ else: ++ str_number = '{:f}'.format(number) + else: + str_number = six.text_type(number) + if str_number[0] == '-': +diff --git a/tests/utils_tests/test_numberformat.py b/tests/utils_tests/test_numberformat.py +index 3dd1b06..769406c 100644 +--- a/tests/utils_tests/test_numberformat.py ++++ b/tests/utils_tests/test_numberformat.py +@@ -60,6 +60,24 @@ class TestNumberFormat(TestCase): + self.assertEqual(nformat(Decimal('1234'), '.', grouping=2, thousand_sep=',', force_grouping=True), '12,34') + self.assertEqual(nformat(Decimal('-1234.33'), '.', decimal_pos=1), '-1234.3') + self.assertEqual(nformat(Decimal('0.00000001'), '.', decimal_pos=8), '0.00000001') ++ # 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: ++ self.assertEqual(nformat(Decimal(value), '.', decimal_pos), expected_value) + + def test_decimal_subclass(self): + class EuroDecimal(Decimal): diff --git a/debian/patches/series b/debian/patches/series index 5bda383eb..ad6685673 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -9,3 +9,4 @@ fix-test-middleware-classes-headers.patch 0016-CVE-2017-12794.patch 0006-Default-to-supporting-Spatialite-4.2.patch 0017-CVE-2019-3498.patch +0018-CVE-2019-6975.patch