File tree Expand file tree Collapse file tree 3 files changed +30
–4
lines changed
Expand file tree Collapse file tree 3 files changed +30
–4
lines changed Original file line number Diff line number Diff line change @@ -229,16 +229,18 @@ def repercent_broken_unicode(path):
229229 repercent-encode any octet produced that is not part of a strictly legal
230230 UTF-8 octet sequence.
231231 """
232+ changed_parts = []
232233 while True :
233234 try :
234235 path .decode ()
235236 except UnicodeDecodeError as e :
236237 # CVE-2019-14235: A recursion shouldn't be used since the exception
237238 # handling uses massive amounts of memory
238239 repercent = quote (path [e .start :e .end ], safe = b"/#%[]=:;$&()+,!?*@'~" )
239- path = path [:e .start ] + repercent .encode () + path [e .end :]
240+ changed_parts .append (path [:e .start ] + repercent .encode ())
241+ path = path [e .end :]
240242 else :
241- return path
243+ return b"" . join ( changed_parts ) + path
242244
243245
244246def filepath_to_uri (path ):
Original file line number Diff line number Diff line change @@ -6,4 +6,9 @@ Django 3.2.21 release notes
66
77Django 3.2.21 fixes a security issue with severity "moderate" in 3.2.20.
88
9- ...
9+ CVE-2023-41164: Potential denial of service vulnerability in ``django.utils.encoding.uri_to_iri()``
10+ ===================================================================================================
11+
12+ ``django.utils.encoding.uri_to_iri()`` was subject to potential denial of
13+ service attack via certain inputs with a very large number of Unicode
14+ characters.
Original file line number Diff line number Diff line change 11import datetime
2+ import inspect
23import sys
34import unittest
45from pathlib import Path
56from unittest import mock
6- from urllib .parse import quote_plus
7+ from urllib .parse import quote , quote_plus
78
89from django .test import SimpleTestCase
910from django .utils .encoding import (
@@ -101,6 +102,24 @@ def test_repercent_broken_unicode_recursion_error(self):
101102 except RecursionError :
102103 self .fail ('Unexpected RecursionError raised.' )
103104
105+ def test_repercent_broken_unicode_small_fragments (self ):
106+ data = b"test\xfc test\xfc test\xfc "
107+ decoded_paths = []
108+
109+ def mock_quote (* args , ** kwargs ):
110+ # The second frame is the call to repercent_broken_unicode().
111+ decoded_paths .append (inspect .currentframe ().f_back .f_locals ["path" ])
112+ return quote (* args , ** kwargs )
113+
114+ with mock .patch ("django.utils.encoding.quote" , mock_quote ):
115+ self .assertEqual (repercent_broken_unicode (data ), b"test%FCtest%FCtest%FC" )
116+
117+ # decode() is called on smaller fragment of the path each time.
118+ self .assertEqual (
119+ decoded_paths ,
120+ [b"test\xfc test\xfc test\xfc " , b"test\xfc test\xfc " , b"test\xfc " ],
121+ )
122+
104123
105124class TestRFC3987IEncodingUtils (unittest .TestCase ):
106125
You can’t perform that action at this time.
0 commit comments