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 <felisiak.mariusz@gmail.com>
This commit is contained in:
Nick Pope 2021-09-03 11:26:27 +02:00 committed by Mariusz Felisiak
parent ec2f6ea9c6
commit 4b82578a60
2 changed files with 22 additions and 6 deletions

View File

@ -56,8 +56,9 @@ class DatabaseCache(BaseDatabaseCache):
key_map = {} key_map = {}
for key in keys: for key in keys:
self.validate_key(key) new_key = self.make_key(key, version)
key_map[self.make_key(key, version)] = key self.validate_key(new_key)
key_map[new_key] = key
db = router.db_for_read(self.cache_model_class) db = router.db_for_read(self.cache_model_class)
connection = connections[db] connection = connections[db]
@ -196,14 +197,16 @@ class DatabaseCache(BaseDatabaseCache):
return True return True
def delete(self, key, version=None): def delete(self, key, version=None):
key = self.make_key(key, version)
self.validate_key(key) 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): def delete_many(self, keys, version=None):
key_list = [] key_list = []
for key in keys: for key in keys:
key = self.make_key(key, version)
self.validate_key(key) self.validate_key(key)
key_list.append(self.make_key(key, version)) key_list.append(key)
self._base_delete_many(key_list) self._base_delete_many(key_list)
def _base_delete_many(self, keys): def _base_delete_many(self, keys):

17
tests/cache/tests.py vendored
View File

@ -675,7 +675,7 @@ class BaseCacheTests:
finally: finally:
cull_cache._max_entries = old_max_entries 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 All the builtin backends should warn (except memcached that should
error) on keys that would be refused by memcached. This encourages error) on keys that would be refused by memcached. This encourages
@ -688,7 +688,7 @@ class BaseCacheTests:
return key return key
old_func = cache.key_func old_func = cache.key_func
cache.key_func = func cache.key_func = key_func or func
tests = [ tests = [
('add', [key, 1]), ('add', [key, 1]),
@ -725,6 +725,19 @@ class BaseCacheTests:
) )
self._perform_invalid_key_test(key, expected_warning) 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): def test_cache_versioning_get_set(self):
# set, using default version = 1 # set, using default version = 1
cache.set('answer1', 42) cache.set('answer1', 42)