From fff8e0f2aebab70b180127441fb86807099319f6 Mon Sep 17 00:00:00 2001 From: Aleksander Machniak Date: Tue, 12 May 2015 09:09:13 +0200 Subject: [PATCH] Fix possible memcache/apc cache data consistency issues (#1490390) And removed unused code --- CHANGELOG | 1 + program/lib/Roundcube/rcube_cache.php | 36 +++++++------------- program/lib/Roundcube/rcube_cache_shared.php | 28 +++++++-------- 3 files changed, 26 insertions(+), 39 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 726b8c44d..85669f0b9 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -26,6 +26,7 @@ CHANGELOG Roundcube Webmail - Fix bug where preview_pane setting wasn't always saved into user preferences (#1490362) - Fix bug where messages count was not updated after message move/delete with skip_deleted=false (#1490372) - Fix security issue in contact photo handling (#1490379) +- Fix possible memcache/apc cache data consistency issues (#1490390) RELEASE 1.1.1 ------------- diff --git a/program/lib/Roundcube/rcube_cache.php b/program/lib/Roundcube/rcube_cache.php index 5b510b5eb..59e190855 100644 --- a/program/lib/Roundcube/rcube_cache.php +++ b/program/lib/Roundcube/rcube_cache.php @@ -265,7 +265,15 @@ class rcube_cache } if ($this->type != 'db') { - if ($this->type == 'memcache') { + $this->load_index(); + + // Consistency check (#1490390) + if (!in_array($key, $this->index)) { + // we always check if the key exist in the index + // to have data in consistent state. Keeping the index consistent + // is needed for keys delete operation when we delete all keys or by prefix. + } + else if ($this->type == 'memcache') { $ckey = $this->ckey($key); $data = $this->db->get($ckey); @@ -418,13 +426,7 @@ class rcube_cache } // Remove keys by name prefix else if ($prefix_mode) { - // handle data inconsistency: it may happen that index - // contains not all existing cache entries, here we could - // handle at least these that were used before the index was read - $index = array_merge($this->index, array_keys($this->cache)); - $index = array_unique($index); - - foreach ($index as $k) { + foreach ($this->index as $k) { if (strpos($k, $key) === 0) { $this->delete_record($k); } @@ -460,13 +462,12 @@ class rcube_cache /** * Adds entry into memcache/apc DB. * - * @param string $key Cache key name - * @param mxied $data Serialized cache data - * @param bollean $index Enables immediate index update + * @param string $key Cache key name + * @param mixed $data Serialized cache data * * @param boolean True on success, False on failure */ - private function add_record($key, $data, $index=false) + private function add_record($key, $data) { if ($this->type == 'memcache') { $result = $this->db->replace($key, $data, MEMCACHE_COMPRESSED, $this->ttl); @@ -487,17 +488,6 @@ class rcube_cache } } - // Update index - if ($index && $result) { - $this->load_index(); - - if (array_search($key, $this->index) === false) { - $this->index[] = $key; - $data = serialize($this->index); - $this->add_record($this->ikey(), $data); - } - } - return $result; } diff --git a/program/lib/Roundcube/rcube_cache_shared.php b/program/lib/Roundcube/rcube_cache_shared.php index 37eb4bd53..e15689598 100644 --- a/program/lib/Roundcube/rcube_cache_shared.php +++ b/program/lib/Roundcube/rcube_cache_shared.php @@ -260,7 +260,15 @@ class rcube_cache_shared } if ($this->type != 'db') { - if ($this->type == 'memcache') { + $this->load_index(); + + // Consistency check (#1490390) + if (!in_array($key, $this->index)) { + // we always check if the key exist in the index + // to have data in consistent state. Keeping the index consistent + // is needed for keys delete operation when we delete all keys or by prefix. + } + else if ($this->type == 'memcache') { $ckey = $this->ckey($key); $data = $this->db->get($ckey); @@ -441,13 +449,12 @@ class rcube_cache_shared /** * Adds entry into memcache/apc DB. * - * @param string $key Cache key name - * @param mxied $data Serialized cache data - * @param bollean $index Enables immediate index update + * @param string $key Cache key name + * @param mixed $data Serialized cache data * * @param boolean True on success, False on failure */ - private function add_record($key, $data, $index=false) + private function add_record($key, $data) { if ($this->type == 'memcache') { $result = $this->db->replace($key, $data, MEMCACHE_COMPRESSED, $this->ttl); @@ -469,17 +476,6 @@ class rcube_cache_shared } } - // Update index - if ($index && $result) { - $this->load_index(); - - if (array_search($key, $this->index) === false) { - $this->index[] = $key; - $data = serialize($this->index); - $this->add_record($this->ikey(), $data); - } - } - return $result; }