diff options
| author | Andre Cruz <andre.cruz@co.sapo.pt> | 2015-01-07 18:41:29 +0000 |
|---|---|---|
| committer | Tim Graham <timograham@gmail.com> | 2016-05-12 10:17:52 -0400 |
| commit | 929684d6ee0efb5afad51dc584489d0437d2451b (patch) | |
| tree | 44714f4502df964790f9db9a4751c843fa49a997 /django/utils | |
| parent | 4065f429f559533f11abbab40624a61027a52b61 (diff) | |
Fixed #21231 -- Enforced a max size for GET/POST values read into memory.
Thanks Tom Christie for review.
Diffstat (limited to 'django/utils')
| -rw-r--r-- | django/utils/http.py | 60 |
1 files changed, 60 insertions, 0 deletions
diff --git a/django/utils/http.py b/django/utils/http.py index 31de726184..151e85de92 100644 --- a/django/utils/http.py +++ b/django/utils/http.py @@ -9,6 +9,7 @@ import unicodedata from binascii import Error as BinasciiError from email.utils import formatdate +from django.core.exceptions import TooManyFieldsSent from django.utils import six from django.utils.datastructures import MultiValueDict from django.utils.encoding import force_bytes, force_str, force_text @@ -34,6 +35,8 @@ ASCTIME_DATE = re.compile(r'^\w{3} %s %s %s %s$' % (__M, __D2, __T, __Y)) RFC3986_GENDELIMS = str(":/?#[]@") RFC3986_SUBDELIMS = str("!$&'()*+,;=") +FIELDS_MATCH = re.compile('[&;]') + @keep_lazy_text def urlquote(url, safe='/'): @@ -314,3 +317,60 @@ def _is_safe_url(url, host): return False return ((not url_info.netloc or url_info.netloc == host) and (not url_info.scheme or url_info.scheme in ['http', 'https'])) + + +def limited_parse_qsl(qs, keep_blank_values=False, encoding='utf-8', + errors='replace', fields_limit=None): + """ + Return a list of key/value tuples parsed from query string. + + Copied from urlparse with an additional "fields_limit" argument. + Copyright (C) 2013 Python Software Foundation (see LICENSE.python). + + Arguments: + + qs: percent-encoded query string to be parsed + + keep_blank_values: flag indicating whether blank values in + percent-encoded queries should be treated as blank strings. A + true value indicates that blanks should be retained as blank + strings. The default false value indicates that blank values + are to be ignored and treated as if they were not included. + + encoding and errors: specify how to decode percent-encoded sequences + into Unicode characters, as accepted by the bytes.decode() method. + + fields_limit: maximum number of fields parsed or an exception + is raised. None means no limit and is the default. + """ + if fields_limit: + pairs = FIELDS_MATCH.split(qs, fields_limit) + if len(pairs) > fields_limit: + raise TooManyFieldsSent( + 'The number of GET/POST parameters exceeded ' + 'settings.DATA_UPLOAD_MAX_NUMBER_FIELDS.' + ) + else: + pairs = FIELDS_MATCH.split(qs) + r = [] + for name_value in pairs: + if not name_value: + continue + nv = name_value.split(str('='), 1) + if len(nv) != 2: + # Handle case of a control-name with no equal sign + if keep_blank_values: + nv.append('') + else: + continue + if len(nv[1]) or keep_blank_values: + if six.PY3: + name = nv[0].replace('+', ' ') + name = unquote(name, encoding=encoding, errors=errors) + value = nv[1].replace('+', ' ') + value = unquote(value, encoding=encoding, errors=errors) + else: + name = unquote(nv[0].replace(b'+', b' ')) + value = unquote(nv[1].replace(b'+', b' ')) + r.append((name, value)) + return r |
