[Adding t...@security.debian.org to CC]

Chris Lamb wrote:

> retitle 922027 CVE-2019-6975: Memory exhaustion in 
> django.utils.numberformat.format()
> severity 922027 grave
> found 922027 1:1.10.7-2+deb9u3
> tags 922027 + security
> thanks

Security team, may I upload this to stretch-security? Diff attached.


Regards,

-- 
      ,''`.
     : :'  :     Chris Lamb
     `. `'`      la...@debian.org 🍥 chris-lamb.co.uk
       `-
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 <la...@debian.org>  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 <carlton.gib...@noumenal.es>
+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

Reply via email to