2
0
Эх сурвалжийг харах

Fixed #31895 -- Fixed crash when decoding invalid session data.

Thanks Matt Hegarty for the report.
Regression in d4fff711d4c97356bd6ba1273d2a5e349326eb5f.
Mariusz Felisiak 4 жил өмнө
parent
commit
4376c2c7f8

+ 9 - 0
django/contrib/sessions/backends/base.py

@@ -121,6 +121,15 @@ class SessionBase:
             return signing.loads(session_data, salt=self.key_salt, serializer=self.serializer)
         # RemovedInDjango40Warning: when the deprecation ends, handle here
         # exceptions similar to what _legacy_decode() does now.
+        except signing.BadSignature:
+            try:
+                # Return an empty session if data is not in the pre-Django 3.1
+                # format.
+                return self._legacy_decode(session_data)
+            except Exception:
+                logger = logging.getLogger('django.security.SuspiciousSession')
+                logger.warning('Session data corrupted')
+                return {}
         except Exception:
             return self._legacy_decode(session_data)
 

+ 3 - 0
docs/releases/3.1.1.txt

@@ -32,3 +32,6 @@ Bugfixes
 
 * Fixed a data loss possibility, following a regression in Django 2.0, when
   copying model instances with a cached fields value (:ticket:`31863`).
+
+* Fixed a regression in Django 3.1 that caused a crash when decoding an invalid
+  session data (:ticket:`31895`).

+ 10 - 5
tests/sessions_tests/tests.py

@@ -333,11 +333,16 @@ class SessionTestsMixin:
             self.assertEqual(self.session._legacy_decode(encoded), data)
 
     def test_decode_failure_logged_to_security(self):
-        bad_encode = base64.b64encode(b'flaskdj:alkdjf').decode('ascii')
-        with self.assertLogs('django.security.SuspiciousSession', 'WARNING') as cm:
-            self.assertEqual({}, self.session.decode(bad_encode))
-        # The failed decode is logged.
-        self.assertIn('corrupted', cm.output[0])
+        tests = [
+            base64.b64encode(b'flaskdj:alkdjf').decode('ascii'),
+            'bad:encoded:value',
+        ]
+        for encoded in tests:
+            with self.subTest(encoded=encoded):
+                with self.assertLogs('django.security.SuspiciousSession', 'WARNING') as cm:
+                    self.assertEqual(self.session.decode(encoded), {})
+                # The failed decode is logged.
+                self.assertIn('Session data corrupted', cm.output[0])
 
     def test_actual_expiry(self):
         # this doesn't work with JSONSerializer (serializing timedelta)