+89
-9
lines changedFilter options
+89
-9
lines changed Original file line number Diff line number Diff line change
@@ -41,7 +41,7 @@
41
41
RFC3986_GENDELIMS = ":/?#[]@"
42
42
RFC3986_SUBDELIMS = "!$&'()*+,;="
43
43
44
-
FIELDS_MATCH = re.compile('[&;]')
44
+
FIELDS_MATCH = re.compile('&')
45
45
46
46
47
47
@keep_lazy_text
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
1
+
===========================
2
+
Django 2.2.19 release notes
3
+
===========================
4
+
5
+
*February 19, 2021*
6
+
7
+
Django 2.2.19 fixes a security issue in 2.2.18.
8
+
9
+
CVE-2021-23336: Web cache poisoning via ``django.utils.http.limited_parse_qsl()``
10
+
=================================================================================
11
+
12
+
Django contains a copy of :func:`urllib.parse.parse_qsl` which was added to
13
+
backport some security fixes. A further security fix has been issued recently
14
+
such that ``parse_qsl()`` no longer allows using ``;`` as a query parameter
15
+
separator by default. Django now includes this fix. See :bpo:`42967` for
16
+
further details.
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
1
+
===========================
2
+
Django 3.0.13 release notes
3
+
===========================
4
+
5
+
*February 19, 2021*
6
+
7
+
Django 3.0.13 fixes a security issue in 3.0.12.
8
+
9
+
CVE-2021-23336: Web cache poisoning via ``django.utils.http.limited_parse_qsl()``
10
+
=================================================================================
11
+
12
+
Django contains a copy of :func:`urllib.parse.parse_qsl` which was added to
13
+
backport some security fixes. A further security fix has been issued recently
14
+
such that ``parse_qsl()`` no longer allows using ``;`` as a query parameter
15
+
separator by default. Django now includes this fix. See :bpo:`42967` for
16
+
further details.
Original file line number Diff line number Diff line change
@@ -25,6 +25,7 @@ versions of the documentation contain the release notes for any later releases.
25
25
.. toctree::
26
26
:maxdepth: 1
27
27
28
+
3.0.13
28
29
3.0.12
29
30
3.0.11
30
31
3.0.10
@@ -44,6 +45,7 @@ versions of the documentation contain the release notes for any later releases.
44
45
.. toctree::
45
46
:maxdepth: 1
46
47
48
+
2.2.19
47
49
2.2.18
48
50
2.2.17
49
51
2.2.16
Original file line number Diff line number Diff line change
@@ -6,7 +6,7 @@
6
6
class ExceptionHandlerTests(SimpleTestCase):
7
7
8
8
def get_suspicious_environ(self):
9
-
payload = FakePayload('a=1&a=2;a=3\r\n')
9
+
payload = FakePayload('a=1&a=2&a=3\r\n')
10
10
return {
11
11
'REQUEST_METHOD': 'POST',
12
12
'CONTENT_TYPE': 'application/x-www-form-urlencoded',
Original file line number Diff line number Diff line change
@@ -11,7 +11,7 @@
11
11
12
12
class DataUploadMaxMemorySizeFormPostTests(SimpleTestCase):
13
13
def setUp(self):
14
-
payload = FakePayload('a=1&a=2;a=3\r\n')
14
+
payload = FakePayload('a=1&a=2&a=3\r\n')
15
15
self.request = WSGIRequest({
16
16
'REQUEST_METHOD': 'POST',
17
17
'CONTENT_TYPE': 'application/x-www-form-urlencoded',
@@ -117,7 +117,7 @@ def test_get_max_fields_exceeded(self):
117
117
request = WSGIRequest({
118
118
'REQUEST_METHOD': 'GET',
119
119
'wsgi.input': BytesIO(b''),
120
-
'QUERY_STRING': 'a=1&a=2;a=3',
120
+
'QUERY_STRING': 'a=1&a=2&a=3',
121
121
})
122
122
request.GET['a']
123
123
@@ -126,7 +126,7 @@ def test_get_max_fields_not_exceeded(self):
126
126
request = WSGIRequest({
127
127
'REQUEST_METHOD': 'GET',
128
128
'wsgi.input': BytesIO(b''),
129
-
'QUERY_STRING': 'a=1&a=2;a=3',
129
+
'QUERY_STRING': 'a=1&a=2&a=3',
130
130
})
131
131
request.GET['a']
132
132
@@ -168,7 +168,7 @@ def test_no_limit(self):
168
168
169
169
class DataUploadMaxNumberOfFieldsFormPost(SimpleTestCase):
170
170
def setUp(self):
171
-
payload = FakePayload("\r\n".join(['a=1&a=2;a=3', '']))
171
+
payload = FakePayload("\r\n".join(['a=1&a=2&a=3', '']))
172
172
self.request = WSGIRequest({
173
173
'REQUEST_METHOD': 'POST',
174
174
'CONTENT_TYPE': 'application/x-www-form-urlencoded',
Original file line number Diff line number Diff line change
@@ -3,14 +3,16 @@
3
3
from datetime import datetime
4
4
from unittest import mock
5
5
6
+
from django.core.exceptions import TooManyFieldsSent
6
7
from django.test import SimpleTestCase, ignore_warnings
7
8
from django.utils.datastructures import MultiValueDict
8
9
from django.utils.deprecation import RemovedInDjango40Warning
9
10
from django.utils.http import (
10
11
base36_to_int, escape_leading_slashes, http_date, int_to_base36,
11
-
is_safe_url, is_same_domain, parse_etags, parse_http_date, quote_etag,
12
-
url_has_allowed_host_and_scheme, urlencode, urlquote, urlquote_plus,
13
-
urlsafe_base64_decode, urlsafe_base64_encode, urlunquote, urlunquote_plus,
12
+
is_safe_url, is_same_domain, limited_parse_qsl, parse_etags,
13
+
parse_http_date, quote_etag, url_has_allowed_host_and_scheme, urlencode,
14
+
urlquote, urlquote_plus, urlsafe_base64_decode, urlsafe_base64_encode,
15
+
urlunquote, urlunquote_plus,
14
16
)
15
17
16
18
@@ -359,3 +361,47 @@ def test(self):
359
361
for url, expected in tests:
360
362
with self.subTest(url=url):
361
363
self.assertEqual(escape_leading_slashes(url), expected)
364
+
365
+
366
+
# Backport of unit tests for urllib.parse.parse_qsl() from Python 3.8.8.
367
+
# Copyright (C) 2021 Python Software Foundation (see LICENSE.python).
368
+
class ParseQSLBackportTests(unittest.TestCase):
369
+
def test_parse_qsl(self):
370
+
tests = [
371
+
('', []),
372
+
('&', []),
373
+
('&&', []),
374
+
('=', [('', '')]),
375
+
('=a', [('', 'a')]),
376
+
('a', [('a', '')]),
377
+
('a=', [('a', '')]),
378
+
('&a=b', [('a', 'b')]),
379
+
('a=a+b&b=b+c', [('a', 'a b'), ('b', 'b c')]),
380
+
('a=1&a=2', [('a', '1'), ('a', '2')]),
381
+
(';a=b', [(';a', 'b')]),
382
+
('a=a+b;b=b+c', [('a', 'a b;b=b c')]),
383
+
]
384
+
for original, expected in tests:
385
+
with self.subTest(original):
386
+
result = limited_parse_qsl(original, keep_blank_values=True)
387
+
self.assertEqual(result, expected, 'Error parsing %r' % original)
388
+
expect_without_blanks = [v for v in expected if len(v[1])]
389
+
result = limited_parse_qsl(original, keep_blank_values=False)
390
+
self.assertEqual(result, expect_without_blanks, 'Error parsing %r' % original)
391
+
392
+
def test_parse_qsl_encoding(self):
393
+
result = limited_parse_qsl('key=\u0141%E9', encoding='latin-1')
394
+
self.assertEqual(result, [('key', '\u0141\xE9')])
395
+
result = limited_parse_qsl('key=\u0141%C3%A9', encoding='utf-8')
396
+
self.assertEqual(result, [('key', '\u0141\xE9')])
397
+
result = limited_parse_qsl('key=\u0141%C3%A9', encoding='ascii')
398
+
self.assertEqual(result, [('key', '\u0141\ufffd\ufffd')])
399
+
result = limited_parse_qsl('key=\u0141%E9-', encoding='ascii')
400
+
self.assertEqual(result, [('key', '\u0141\ufffd-')])
401
+
result = limited_parse_qsl('key=\u0141%E9-', encoding='ascii', errors='ignore')
402
+
self.assertEqual(result, [('key', '\u0141-')])
403
+
404
+
def test_parse_qsl_field_limit(self):
405
+
with self.assertRaises(TooManyFieldsSent):
406
+
limited_parse_qsl('&'.join(['a=a'] * 11), fields_limit=10)
407
+
limited_parse_qsl('&'.join(['a=a'] * 10), fields_limit=10)
You can’t perform that action at this time.
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4