Skip to content

Commit

Permalink
bug #27416 TagAwareAdapter over non-binary memcached connections corr…
Browse files Browse the repository at this point in the history
…upts memcache (Aleksey Prilipko)

This PR was merged into the 3.4 branch.

Discussion
----------

TagAwareAdapter over non-binary memcached connections corrupts memcache

| Q             | A
| ------------- | ---
| Branch?       | 3.4
| Bug fix?      | yes
| New feature?  | no
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | no
| Fixed tickets | #27405
| License       | MIT
| Doc PR        |

TagAwareAdapter uses non-ascii symbols in key names. It breaks memcached connections in non-binary mode.

Commits
-------

67d4e6d bug #27405 [Cache] TagAwareAdapter should not corrupt memcached connection in ascii mode
  • Loading branch information
nicolas-grekas committed Jun 8, 2018
2 parents 151c406 + 67d4e6d commit 88098f3
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 4 deletions.
@@ -0,0 +1,25 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Component\Cache\Tests\Simple;

use Symfony\Component\Cache\Adapter\AbstractAdapter;
use Symfony\Component\Cache\Simple\MemcachedCache;

class MemcachedCacheTextModeTest extends MemcachedCacheTest
{
public function createSimpleCache($defaultLifetime = 0)
{
$client = AbstractAdapter::createConnection('memcached://'.getenv('MEMCACHED_HOST'), array('binary_protocol' => false));

return new MemcachedCache($client, str_replace('\\', '.', __CLASS__), $defaultLifetime);
}
}
23 changes: 19 additions & 4 deletions src/Symfony/Component/Cache/Traits/MemcachedTrait.php
Expand Up @@ -198,7 +198,12 @@ protected function doSave(array $values, $lifetime)
$lifetime += time();
}

return $this->checkResultCode($this->getClient()->setMulti($values, $lifetime));
$encodedValues = array();
foreach ($values as $key => $value) {
$encodedValues[rawurlencode($key)] = $value;
}

return $this->checkResultCode($this->getClient()->setMulti($encodedValues, $lifetime));
}

/**
Expand All @@ -208,7 +213,16 @@ protected function doFetch(array $ids)
{
$unserializeCallbackHandler = ini_set('unserialize_callback_func', __CLASS__.'::handleUnserializeCallback');
try {
return $this->checkResultCode($this->getClient()->getMulti($ids));
$encodedIds = array_map('rawurlencode', $ids);

$encodedResult = $this->checkResultCode($this->getClient()->getMulti($encodedIds));

$result = array();
foreach ($encodedResult as $key => $value) {
$result[rawurldecode($key)] = $value;
}

return $result;
} catch (\Error $e) {
throw new \ErrorException($e->getMessage(), $e->getCode(), E_ERROR, $e->getFile(), $e->getLine());
} finally {
Expand All @@ -221,7 +235,7 @@ protected function doFetch(array $ids)
*/
protected function doHave($id)
{
return false !== $this->getClient()->get($id) || $this->checkResultCode(\Memcached::RES_SUCCESS === $this->client->getResultCode());
return false !== $this->getClient()->get(rawurlencode($id)) || $this->checkResultCode(\Memcached::RES_SUCCESS === $this->client->getResultCode());
}

/**
Expand All @@ -230,7 +244,8 @@ protected function doHave($id)
protected function doDelete(array $ids)
{
$ok = true;
foreach ($this->checkResultCode($this->getClient()->deleteMulti($ids)) as $result) {
$encodedIds = array_map('rawurlencode', $ids);
foreach ($this->checkResultCode($this->getClient()->deleteMulti($encodedIds)) as $result) {
if (\Memcached::RES_SUCCESS !== $result && \Memcached::RES_NOTFOUND !== $result) {
$ok = false;
}
Expand Down

0 comments on commit 88098f3

Please sign in to comment.