diff options
author | Nick Pope <nick.pope@flightdataservices.com> | 2019-11-04 12:06:49 +0000 |
---|---|---|
committer | Mariusz Felisiak <felisiak.mariusz@gmail.com> | 2020-09-03 14:24:42 +0200 |
commit | fd209f62f1d83233cc634443cfac5ee4328d98b8 (patch) | |
tree | 476f3b0c54339831288823b75afa74822198188a /django/http/request.py | |
parent | 8d59075184f4cd2852b374359850ff7aeb412ec1 (diff) | |
download | django-fd209f62f1d83233cc634443cfac5ee4328d98b8.tar.gz |
Refs #21231 -- Backport urllib.parse.parse_qsl() from Python 3.8.
Diffstat (limited to 'django/http/request.py')
-rw-r--r-- | django/http/request.py | 31 |
1 files changed, 25 insertions, 6 deletions
diff --git a/django/http/request.py b/django/http/request.py index 083bf2d80f..addcf05329 100644 --- a/django/http/request.py +++ b/django/http/request.py @@ -4,12 +4,12 @@ import copy import warnings from io import BytesIO from itertools import chain -from urllib.parse import quote, urlencode, urljoin, urlsplit +from urllib.parse import parse_qsl, quote, urlencode, urljoin, urlsplit from django.conf import settings from django.core import signing from django.core.exceptions import ( - DisallowedHost, ImproperlyConfigured, RequestDataTooBig, + DisallowedHost, ImproperlyConfigured, RequestDataTooBig, TooManyFieldsSent, ) from django.core.files import uploadhandler from django.http.multipartparser import MultiPartParser, MultiPartParserError @@ -19,11 +19,20 @@ from django.utils.datastructures import ( from django.utils.deprecation import RemovedInDjango40Warning from django.utils.encoding import escape_uri_path, iri_to_uri from django.utils.functional import cached_property -from django.utils.http import is_same_domain, limited_parse_qsl +from django.utils.http import is_same_domain +from django.utils.inspect import func_supports_parameter from django.utils.regex_helper import _lazy_re_compile from .multipartparser import parse_header +# TODO: Remove when dropping support for PY37. inspect.signature() is used to +# detect whether the max_num_fields argument is available as this security fix +# was backported to Python 3.6.8 and 3.7.2, and may also have been applied by +# downstream package maintainers to other versions in their repositories. +if func_supports_parameter(parse_qsl, 'max_num_fields'): + from django.utils.http import parse_qsl + + RAISE_ERROR = object() host_validation_re = _lazy_re_compile(r"^([a-z0-9.-]+|\[[a-f0-9]*:[a-f0-9\.:]+\])(:\d+)?$") @@ -446,8 +455,8 @@ class QueryDict(MultiValueDict): query_string = query_string or '' parse_qsl_kwargs = { 'keep_blank_values': True, - 'fields_limit': settings.DATA_UPLOAD_MAX_NUMBER_FIELDS, 'encoding': self.encoding, + 'max_num_fields': settings.DATA_UPLOAD_MAX_NUMBER_FIELDS, } if isinstance(query_string, bytes): # query_string normally contains URL-encoded data, a subset of ASCII. @@ -456,8 +465,18 @@ class QueryDict(MultiValueDict): except UnicodeDecodeError: # ... but some user agents are misbehaving :-( query_string = query_string.decode('iso-8859-1') - for key, value in limited_parse_qsl(query_string, **parse_qsl_kwargs): - self.appendlist(key, value) + try: + for key, value in parse_qsl(query_string, **parse_qsl_kwargs): + self.appendlist(key, value) + except ValueError as e: + # ValueError can also be raised if the strict_parsing argument to + # parse_qsl() is True. As that is not used by Django, assume that + # the exception was raised by exceeding the value of max_num_fields + # instead of fragile checks of exception message strings. + raise TooManyFieldsSent( + 'The number of GET/POST parameters exceeded ' + 'settings.DATA_UPLOAD_MAX_NUMBER_FIELDS.' + ) from e self._mutable = mutable @classmethod |