From e399272bed9cf28634a6866bea9bb74c71159291 Mon Sep 17 00:00:00 2001 From: amalia Date: Fri, 10 Feb 2017 09:30:51 +0100 Subject: [PATCH] [1.10.x] Fixed #27820 -- Fixed RequestDataTooBig/TooManyFieldsSent crash. Backport of 2f10216f84b55920de25422842a66260219e393f from master --- django/core/handlers/exception.py | 10 +++++++++- docs/releases/1.10.6.txt | 3 +++ tests/handlers/test_exception.py | 29 +++++++++++++++++++++++++++++ 3 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 tests/handlers/test_exception.py diff --git a/django/core/handlers/exception.py b/django/core/handlers/exception.py index 9edf457ad1..d2d9f3d5f1 100644 --- a/django/core/handlers/exception.py +++ b/django/core/handlers/exception.py @@ -7,7 +7,10 @@ from functools import wraps from django.conf import settings from django.core import signals -from django.core.exceptions import PermissionDenied, SuspiciousOperation +from django.core.exceptions import ( + PermissionDenied, RequestDataTooBig, SuspiciousOperation, + TooManyFieldsSent, +) from django.http import Http404 from django.http.multipartparser import MultiPartParserError from django.urls import get_resolver, get_urlconf @@ -65,6 +68,11 @@ def response_for_exception(request, exc): response = get_exception_response(request, get_resolver(get_urlconf()), 400, exc) elif isinstance(exc, SuspiciousOperation): + if isinstance(exc, (RequestDataTooBig, TooManyFieldsSent)): + # POST data can't be accessed again, otherwise the original + # exception would be raised. + request._mark_post_parse_error() + # The request logger receives events for any problematic request # The security logger receives events for all SuspiciousOperations security_logger = logging.getLogger('django.security.%s' % exc.__class__.__name__) diff --git a/docs/releases/1.10.6.txt b/docs/releases/1.10.6.txt index dc5c49938f..483854c0e6 100644 --- a/docs/releases/1.10.6.txt +++ b/docs/releases/1.10.6.txt @@ -11,3 +11,6 @@ Bugfixes * Fixed ``ClearableFileInput``’s "Clear" checkbox on model form fields where the model field has a ``default`` (:ticket:`27805`). + +* Fixed ``RequestDataTooBig`` and ``TooManyFieldsSent`` exceptions crashing + rather than generating a bad request response (:ticket:`27820`). diff --git a/tests/handlers/test_exception.py b/tests/handlers/test_exception.py new file mode 100644 index 0000000000..ab21c31611 --- /dev/null +++ b/tests/handlers/test_exception.py @@ -0,0 +1,29 @@ +from django.core.handlers.wsgi import WSGIHandler +from django.test import SimpleTestCase, override_settings +from django.test.client import FakePayload + + +@override_settings(ROOT_URLCONF='handlers.urls') +class ExceptionHandlerTests(SimpleTestCase): + + def get_suspicious_environ(self): + payload = FakePayload('a=1&a=2;a=3\r\n') + return { + 'REQUEST_METHOD': 'POST', + 'CONTENT_TYPE': 'application/x-www-form-urlencoded', + 'CONTENT_LENGTH': len(payload), + 'wsgi.input': payload, + 'SERVER_NAME': 'test', + 'SERVER_PORT': '8000', + 'PATH_INFO': '/malformed_post/', + } + + @override_settings(DATA_UPLOAD_MAX_MEMORY_SIZE=12) + def test_data_upload_max_memory_size_exceeded(self): + response = WSGIHandler()(self.get_suspicious_environ(), lambda *a, **k: None) + self.assertEqual(response.status_code, 400) + + @override_settings(DATA_UPLOAD_MAX_NUMBER_FIELDS=2) + def test_data_upload_max_number_fields_exceeded(self): + response = WSGIHandler()(self.get_suspicious_environ(), lambda *a, **k: None) + self.assertEqual(response.status_code, 400)