From 4b82578a6045746e7c470b7881dfcf182fd57048 Mon Sep 17 00:00:00 2001 From: Nick Pope Date: Fri, 3 Sep 2021 11:26:27 +0200 Subject: [PATCH] Refs #33060 -- Ensured cache backends validate keys. The validate_key() function should be called after make_key() to ensure that the validation is performed on the key that will actually be stored in the cache. Co-authored-by: Mariusz Felisiak --- django/core/cache/backends/db.py | 11 +++++++---- tests/cache/tests.py | 17 +++++++++++++++-- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/django/core/cache/backends/db.py b/django/core/cache/backends/db.py index b84885f1ef..63598007d0 100644 --- a/django/core/cache/backends/db.py +++ b/django/core/cache/backends/db.py @@ -56,8 +56,9 @@ class DatabaseCache(BaseDatabaseCache): key_map = {} for key in keys: - self.validate_key(key) - key_map[self.make_key(key, version)] = key + new_key = self.make_key(key, version) + self.validate_key(new_key) + key_map[new_key] = key db = router.db_for_read(self.cache_model_class) connection = connections[db] @@ -196,14 +197,16 @@ class DatabaseCache(BaseDatabaseCache): return True def delete(self, key, version=None): + key = self.make_key(key, version) self.validate_key(key) - return self._base_delete_many([self.make_key(key, version)]) + return self._base_delete_many([key]) def delete_many(self, keys, version=None): key_list = [] for key in keys: + key = self.make_key(key, version) self.validate_key(key) - key_list.append(self.make_key(key, version)) + key_list.append(key) self._base_delete_many(key_list) def _base_delete_many(self, keys): diff --git a/tests/cache/tests.py b/tests/cache/tests.py index 1b40def85a..0e2f5f7d1f 100644 --- a/tests/cache/tests.py +++ b/tests/cache/tests.py @@ -675,7 +675,7 @@ class BaseCacheTests: finally: cull_cache._max_entries = old_max_entries - def _perform_invalid_key_test(self, key, expected_warning): + def _perform_invalid_key_test(self, key, expected_warning, key_func=None): """ All the builtin backends should warn (except memcached that should error) on keys that would be refused by memcached. This encourages @@ -688,7 +688,7 @@ class BaseCacheTests: return key old_func = cache.key_func - cache.key_func = func + cache.key_func = key_func or func tests = [ ('add', [key, 1]), @@ -725,6 +725,19 @@ class BaseCacheTests: ) self._perform_invalid_key_test(key, expected_warning) + def test_invalid_with_version_key_length(self): + # Custom make_key() that adds a version to the key and exceeds the + # limit. + def key_func(key, *args): + return key + ':1' + + key = 'a' * 249 + expected_warning = ( + 'Cache key will cause errors if used with memcached: ' + '%r (longer than %s)' % (key_func(key), 250) + ) + self._perform_invalid_key_test(key, expected_warning, key_func=key_func) + def test_cache_versioning_get_set(self): # set, using default version = 1 cache.set('answer1', 42)