From f7c397191f0089496c2ecd2f8a63851fbe4eaee5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Mon, 15 Jan 2024 23:48:50 +0100 Subject: [PATCH] Prevent modify mutable cached value The cached values are copied when set and copied again when returned so the stored values can never be modified. Closes #9558 (grafted from 7bbbb91621ab3759dfdc04de3aa1754c89ef145d) --HG-- branch : 7.0 --- trytond/trytond/cache.py | 5 +++-- trytond/trytond/tests/test_cache.py | 9 +++++++++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/trytond/trytond/cache.py b/trytond/trytond/cache.py index 3c26c08a73..ef045dace7 100644 --- a/trytond/trytond/cache.py +++ b/trytond/trytond/cache.py @@ -7,6 +7,7 @@ import os import selectors import threading from collections import OrderedDict, defaultdict +from copy import deepcopy from weakref import WeakKeyDictionary from sql import Table @@ -190,7 +191,7 @@ class MemoryCache(BaseCache): return default cache[key] = (expire, result) self.hit += 1 - return result + return deepcopy(result) except (KeyError, TypeError): self.miss += 1 return default @@ -203,7 +204,7 @@ class MemoryCache(BaseCache): else: expire = None try: - cache[key] = (expire, value) + cache[key] = (expire, deepcopy(value)) except TypeError: pass return value diff --git a/trytond/trytond/tests/test_cache.py b/trytond/trytond/tests/test_cache.py index bba1c177a8..a6f37ad433 100644 --- a/trytond/trytond/tests/test_cache.py +++ b/trytond/trytond/tests/test_cache.py @@ -121,6 +121,15 @@ class MemoryCacheTestCase(unittest.TestCase): self.assertEqual(cache.get('foo'), 'bar') + @with_transaction() + def test_memory_cache_mutable(self): + "Test MemoryCache with mutable value" + value = ['bar'] + cache.set('foo', value) + value.remove('bar') + + self.assertEqual(cache.get('foo'), ['bar']) + @with_transaction() def test_memory_cache_drop(self): "Test MemoryCache drop"