Package: python-django / 1:1.10.7-2+deb9u9

0024-CVE-2019-14235.patch Patch series | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
From: Chris Lamb <lamby@debian.org>
Date: Thu, 8 Aug 2019 10:36:25 +0100
Subject: CVE-2019-14235

Backported from
<https://github.com/django/django/commit/869b34e9b3be3a4cfcb3a145f218ffd3f5e3fd79>
---
 django/utils/encoding.py           | 17 ++++++++++-------
 tests/utils_tests/test_encoding.py | 12 +++++++++++-
 2 files changed, 21 insertions(+), 8 deletions(-)

diff --git a/django/utils/encoding.py b/django/utils/encoding.py
index 66077e2..2a03d10 100644
--- a/django/utils/encoding.py
+++ b/django/utils/encoding.py
@@ -236,13 +236,16 @@ def repercent_broken_unicode(path):
     we need to re-percent-encode any octet produced that is not part of a
     strictly legal UTF-8 octet sequence.
     """
-    try:
-        path.decode('utf-8')
-    except UnicodeDecodeError as e:
-        repercent = quote(path[e.start:e.end], safe=b"/#%[]=:;$&()+,!?*@'~")
-        path = repercent_broken_unicode(
-            path[:e.start] + force_bytes(repercent) + path[e.end:])
-    return path
+    while True:
+        try:
+            path.decode('utf-8')
+        except UnicodeDecodeError as e:
+            # CVE-2019-14235: A recursion shouldn't be used since the exception
+            # handling uses massive amounts of memory
+            repercent = quote(path[e.start:e.end], safe=b"/#%[]=:;$&()+,!?*@'~")
+            path = path[:e.start] + force_bytes(repercent) + path[e.end:]
+        else:
+            return path
 
 
 def filepath_to_uri(path):
diff --git a/tests/utils_tests/test_encoding.py b/tests/utils_tests/test_encoding.py
index 5ddb18d..df4cc9d 100644
--- a/tests/utils_tests/test_encoding.py
+++ b/tests/utils_tests/test_encoding.py
@@ -2,12 +2,13 @@
 from __future__ import unicode_literals
 
 import datetime
+import sys
 import unittest
 
 from django.utils import six
 from django.utils.encoding import (
     escape_uri_path, filepath_to_uri, force_bytes, force_text, iri_to_uri,
-    smart_text, uri_to_iri,
+    repercent_broken_unicode, smart_text, uri_to_iri,
 )
 from django.utils.functional import SimpleLazyObject
 from django.utils.http import urlquote_plus
@@ -76,6 +77,15 @@ class TestEncodingUtils(unittest.TestCase):
         self.assertEqual(smart_text(1), '1')
         self.assertEqual(smart_text('foo'), 'foo')
 
+    def test_repercent_broken_unicode_recursion_error(self):
+        # Prepare a string long enough to force a recursion error if the tested
+        # function uses recursion.
+        data = b'\xfc' * sys.getrecursionlimit()
+        try:
+            self.assertEqual(repercent_broken_unicode(data), b'%FC' * sys.getrecursionlimit())
+        except RecursionError:
+            self.fail('Unexpected RecursionError raised.')
+
 
 class TestRFC3987IEncodingUtils(unittest.TestCase):