From cd19db10df6225e01b77685397a88c9cdf216dd1 Mon Sep 17 00:00:00 2001
From: Chris Jerdonek <chris.jerdonek@gmail.com>
Date: Mon, 31 May 2021 04:26:11 -0700
Subject: [PATCH] Fixed #32796 -- Changed CsrfViewMiddleware to fail earlier on
 badly formatted cookie tokens.

---
 django/middleware/csrf.py | 23 +++++++++++++++--------
 tests/csrf_tests/tests.py |  4 ++--
 2 files changed, 17 insertions(+), 10 deletions(-)

diff --git a/django/middleware/csrf.py b/django/middleware/csrf.py
index 3febfd9486..5d77b19c7c 100644
--- a/django/middleware/csrf.py
+++ b/django/middleware/csrf.py
@@ -217,14 +217,12 @@ class CsrfViewMiddleware(MiddlewareMixin):
             except KeyError:
                 return None
 
-            try:
-                csrf_token = _sanitize_token(cookie_token)
-            except InvalidTokenFormat:
-                csrf_token = _get_new_csrf_token()
+            # This can raise InvalidTokenFormat.
+            csrf_token = _sanitize_token(cookie_token)
 
             if csrf_token != cookie_token:
-                # Cookie token needed to be replaced;
-                # the cookie needs to be reset.
+                # Then the cookie token had length CSRF_SECRET_LENGTH, so flag
+                # to replace it with the masked version.
                 request.csrf_cookie_needs_reset = True
             return csrf_token
 
@@ -318,7 +316,12 @@ class CsrfViewMiddleware(MiddlewareMixin):
             raise RejectRequest(REASON_BAD_REFERER % referer.geturl())
 
     def process_request(self, request):
-        csrf_token = self._get_token(request)
+        try:
+            csrf_token = self._get_token(request)
+        except InvalidTokenFormat:
+            csrf_token = _get_new_csrf_token()
+            request.csrf_cookie_needs_reset = True
+
         if csrf_token is not None:
             # Use same token next time.
             request.META['CSRF_COOKIE'] = csrf_token
@@ -374,7 +377,11 @@ class CsrfViewMiddleware(MiddlewareMixin):
         # Access csrf_token via self._get_token() as rotate_token() may have
         # been called by an authentication middleware during the
         # process_request() phase.
-        csrf_token = self._get_token(request)
+        try:
+            csrf_token = self._get_token(request)
+        except InvalidTokenFormat as exc:
+            return self._reject(request, f'CSRF cookie {exc.reason}.')
+
         if csrf_token is None:
             # No CSRF cookie. For POST requests, we insist on a CSRF cookie,
             # and in this way we can avoid all CSRF attacks, including login
diff --git a/tests/csrf_tests/tests.py b/tests/csrf_tests/tests.py
index f68828065f..7cf69fd6c5 100644
--- a/tests/csrf_tests/tests.py
+++ b/tests/csrf_tests/tests.py
@@ -863,14 +863,14 @@ class CsrfViewMiddlewareTests(CsrfViewMiddlewareTestMixin, SimpleTestCase):
         If the CSRF cookie has invalid characters in a POST request, the
         middleware rejects the incoming request.
         """
-        self._check_bad_or_missing_cookie(64 * '*', REASON_CSRF_TOKEN_MISSING)
+        self._check_bad_or_missing_cookie(64 * '*', 'CSRF cookie has invalid characters.')
 
     def test_bad_csrf_cookie_length(self):
         """
         If the CSRF cookie has an incorrect length in a POST request, the
         middleware rejects the incoming request.
         """
-        self._check_bad_or_missing_cookie(16 * 'a', REASON_CSRF_TOKEN_MISSING)
+        self._check_bad_or_missing_cookie(16 * 'a', 'CSRF cookie has incorrect length.')
 
     def test_process_view_token_too_long(self):
         """