From 815e7a57216b3e6ef716e924016acb09633ea8d1 Mon Sep 17 00:00:00 2001 From: Tim Graham Date: Wed, 25 Jun 2014 06:52:25 -0400 Subject: [PATCH] Fixed #20128 -- Made CsrfViewMiddleware ignore IOError when reading POST data. Thanks Walter Doekes. --- django/middleware/csrf.py | 10 +++++++++- tests/csrf_tests/tests.py | 41 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+), 1 deletion(-) diff --git a/django/middleware/csrf.py b/django/middleware/csrf.py index eb7fe7d8cb..54067fd0be 100644 --- a/django/middleware/csrf.py +++ b/django/middleware/csrf.py @@ -167,7 +167,15 @@ class CsrfViewMiddleware(object): # Check non-cookie token for match. request_csrf_token = "" if request.method == "POST": - request_csrf_token = request.POST.get('csrfmiddlewaretoken', '') + try: + request_csrf_token = request.POST.get('csrfmiddlewaretoken', '') + except IOError: + # Handle a broken connection before we've completed reading + # the POST data. process_view shouldn't raise any + # exceptions, so we'll ignore and serve the user a 403 + # (assuming they're still listening, which they probably + # aren't because of the error). + pass if request_csrf_token == "": # Fall back to X-CSRFToken, to make things easier for AJAX, diff --git a/tests/csrf_tests/tests.py b/tests/csrf_tests/tests.py index 6199ca84bd..b12e409955 100644 --- a/tests/csrf_tests/tests.py +++ b/tests/csrf_tests/tests.py @@ -428,3 +428,44 @@ class CsrfViewMiddlewareTest(TestCase): resp2 = CsrfViewMiddleware().process_response(req, resp) max_age = resp2.cookies.get('csrfcookie').get('max-age') self.assertEqual(max_age, '') + + def test_post_data_read_failure(self): + """ + #20128 -- IOErrors during POST data reading should be caught and + treated as if the POST data wasn't there. + """ + class CsrfPostRequest(HttpRequest): + """ + HttpRequest that can raise an IOError when accessing POST data + """ + def __init__(self, token, raise_error): + super(CsrfPostRequest, self).__init__() + self.method = 'POST' + + self.raise_error = False + self.COOKIES[settings.CSRF_COOKIE_NAME] = token + self.POST['csrfmiddlewaretoken'] = token + self.raise_error = raise_error + + def _load_post_and_files(self): + raise IOError('error reading input data') + + def _get_post(self): + if self.raise_error: + self._load_post_and_files() + return self._post + + def _set_post(self, post): + self._post = post + + POST = property(_get_post, _set_post) + + token = 'ABC' + + req = CsrfPostRequest(token, raise_error=False) + resp = CsrfViewMiddleware().process_view(req, post_form_view, (), {}) + self.assertEqual(resp, None) + + req = CsrfPostRequest(token, raise_error=True) + resp = CsrfViewMiddleware().process_view(req, post_form_view, (), {}) + self.assertEqual(resp.status_code, 403)