Fixed #23887 -- Returned Bad Request for multipart parsing fails

Thanks Antti Häyrynen and Tim Graham for the report, and Aymeric
Augustin for the review.
This commit is contained in:
Claude Paroz 2014-11-21 21:47:46 +01:00
parent b0a58b9085
commit b38637d581
4 changed files with 31 additions and 0 deletions

View File

@ -10,6 +10,7 @@ from django.core import urlresolvers
from django.core import signals from django.core import signals
from django.core.exceptions import MiddlewareNotUsed, PermissionDenied, SuspiciousOperation from django.core.exceptions import MiddlewareNotUsed, PermissionDenied, SuspiciousOperation
from django.db import connections, transaction from django.db import connections, transaction
from django.http.multipartparser import MultiPartParserError
from django.utils.encoding import force_text from django.utils.encoding import force_text
from django.utils.module_loading import import_string from django.utils.module_loading import import_string
from django.utils import six from django.utils import six
@ -176,6 +177,15 @@ class BaseHandler(object):
}) })
response = self.get_exception_response(request, resolver, 403) response = self.get_exception_response(request, resolver, 403)
except MultiPartParserError:
logger.warning(
'Bad request (Unable to parse request body): %s', request.path,
extra={
'status_code': 400,
'request': request
})
response = self.get_exception_response(request, resolver, 400)
except SuspiciousOperation as e: except SuspiciousOperation as e:
# The request logger receives events for any problematic request # The request logger receives events for any problematic request
# The security logger receives events for all SuspiciousOperations # The security logger receives events for all SuspiciousOperations

View File

@ -93,6 +93,19 @@ class HandlerTests(TestCase):
# latest versions. # latest versions.
self.assertIsInstance(request.COOKIES, dict) self.assertIsInstance(request.COOKIES, dict)
@override_settings(ROOT_URLCONF='handlers.urls')
def test_invalid_multipart_boundary(self):
"""
Invalid boundary string should produce a "Bad Request" response, not a
server error (#23887).
"""
environ = RequestFactory().post('/malformed_post/').environ
environ['CONTENT_TYPE'] = 'multipart/form-data; boundary=WRONG\x07'
handler = WSGIHandler()
response = handler(environ, lambda *a, **k: None)
# Expect "bad request" response
self.assertEqual(response.status_code, 400)
@override_settings(ROOT_URLCONF='handlers.urls') @override_settings(ROOT_URLCONF='handlers.urls')
class TransactionsPerRequestTests(TransactionTestCase): class TransactionsPerRequestTests(TransactionTestCase):

View File

@ -10,4 +10,5 @@ urlpatterns = [
url(r'^in_transaction/$', views.in_transaction), url(r'^in_transaction/$', views.in_transaction),
url(r'^not_in_transaction/$', views.not_in_transaction), url(r'^not_in_transaction/$', views.not_in_transaction),
url(r'^suspicious/$', views.suspicious), url(r'^suspicious/$', views.suspicious),
url(r'^malformed_post/$', views.malformed_post),
] ]

View File

@ -3,6 +3,7 @@ from __future__ import unicode_literals
from django.core.exceptions import SuspiciousOperation from django.core.exceptions import SuspiciousOperation
from django.db import connection, transaction from django.db import connection, transaction
from django.http import HttpResponse, StreamingHttpResponse from django.http import HttpResponse, StreamingHttpResponse
from django.views.decorators.csrf import csrf_exempt
def regular(request): def regular(request):
@ -24,3 +25,9 @@ def not_in_transaction(request):
def suspicious(request): def suspicious(request):
raise SuspiciousOperation('dubious') raise SuspiciousOperation('dubious')
@csrf_exempt
def malformed_post(request):
request.POST
return HttpResponse()