From 6599ae3ddc2340ef050046e3162e6ca48a2e7802 Mon Sep 17 00:00:00 2001 From: Jonathan Druart Date: Fri, 8 Apr 2016 13:08:55 +0100 Subject: [PATCH] Bug 16229: Deep copy on first L2 fetch When a value exists in L2 cache but not in L1 cache, it should be deep copied if needed (i.e. not a scalar). Otherwise the calling code is able to modify the value in cache. Note that is theoretical, it's possible that no code does that. Signed-off-by: Jacek Ablewicz Signed-off-by: Tomas Cohen Arazi Signed-off-by: Brendan Gallagher (cherry picked from commit 956dc953b52a1fd525bc75682bbdfe6848683ace) Signed-off-by: Julian Maurice --- Koha/Cache.pm | 2 ++ t/Cache.t | 10 ++++++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/Koha/Cache.pm b/Koha/Cache.pm index f980da5247..5e4471c972 100644 --- a/Koha/Cache.pm +++ b/Koha/Cache.pm @@ -321,6 +321,8 @@ sub get_from_cache { # Otherwise the L1 cache won't ever be populated $L1_cache{$key} = $value; + $value = clone $value if ref $L1_cache{$key} and not $unsafe; + return $value; } diff --git a/t/Cache.t b/t/Cache.t index c8887db1bf..7ec72efbc8 100644 --- a/t/Cache.t +++ b/t/Cache.t @@ -17,7 +17,7 @@ use Modern::Perl; -use Test::More tests => 39; +use Test::More tests => 40; my $destructorcount = 0; @@ -34,7 +34,7 @@ SKIP: { $ENV{ MEMCACHED_NAMESPACE } = 'unit_tests'; my $cache = Koha::Cache->get_instance(); - skip "Cache not enabled", 33 + skip "Cache not enabled", 34 unless ( $cache->is_cache_active() && defined $cache ); # test fetching an item that isnt in the cache @@ -182,6 +182,12 @@ SKIP: { $item_from_cache = $cache->get_from_cache('test_deep_copy_array'); @$item_from_cache = qw( another array ref ); is_deeply( $cache->get_from_cache('test_deep_copy_array'), [ qw ( an array ref ) ], 'An array will be deep copied'); + + $cache->flush_L1_cache(); + $item_from_cache = $cache->get_from_cache('test_deep_copy_array'); + @$item_from_cache = qw( another array ref ); + is_deeply( $cache->get_from_cache('test_deep_copy_array'), [ qw ( an array ref ) ], 'An array will be deep copied even it is the first fetch from L2'); + $item_from_cache = $cache->get_from_cache('test_deep_copy_array', { unsafe => 1 }); @$item_from_cache = qw( another array ref ); is_deeply( $cache->get_from_cache('test_deep_copy_array'), [ qw ( another array ref ) ], 'An array will not be deep copied if the unsafe flag is set'); -- 2.39.5