Skip to content
Permalink
Browse files

[1.11.x] Fixed CVE-2019-14235 -- Fixed potential memory exhaustion in…

… django.utils.encoding.uri_to_iri().

Thanks to Guido Vranken for initial report.
  • Loading branch information...
apollo13 authored and carltongibson committed Jul 19, 2019
1 parent ed682a2 commit 869b34e9b3be3a4cfcb3a145f218ffd3f5e3fd79
Showing with 31 additions and 8 deletions.
  1. +10 −7 django/utils/encoding.py
  2. +10 −0 docs/releases/1.11.23.txt
  3. +11 −1 tests/utils_tests/test_encoding.py
@@ -237,13 +237,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):
@@ -45,3 +45,13 @@ CVE-2019-14234: SQL injection possibility in key and index lookups for ``JSONFie
<hstorefield.key>` for :class:`~django.contrib.postgres.fields.HStoreField`
were subject to SQL injection, using a suitably crafted dictionary, with
dictionary expansion, as the ``**kwargs`` passed to ``QuerySet.filter()``.

CVE-2019-14235: Potential memory exhaustion in ``django.utils.encoding.uri_to_iri()``
=====================================================================================

If passed certain inputs, :func:`django.utils.encoding.uri_to_iri` could lead
to significant memory usage due to excessive recursion when re-percent-encoding
invalid UTF-8 octet sequences.

``uri_to_iri()`` now avoids recursion when re-percent-encoding invalid UTF-8
octet sequences.
@@ -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 @@ def __unicode__(self):
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):

0 comments on commit 869b34e

Please sign in to comment.
You can’t perform that action at this time.