Skip to content

Commit 471a50b

Browse files
bug #27416 TagAwareAdapter over non-binary memcached connections corrupts 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 ------- 67d4e6dd29 bug #27405 [Cache] TagAwareAdapter should not corrupt memcached connection in ascii mode
2 parents 503168d + 25f44c5 commit 471a50b

File tree

2 files changed

+44
-4
lines changed

2 files changed

+44
-4
lines changed
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Cache\Tests\Simple;
13+
14+
use Symfony\Component\Cache\Adapter\AbstractAdapter;
15+
use Symfony\Component\Cache\Simple\MemcachedCache;
16+
17+
class MemcachedCacheTextModeTest extends MemcachedCacheTest
18+
{
19+
public function createSimpleCache($defaultLifetime = 0)
20+
{
21+
$client = AbstractAdapter::createConnection('memcached://'.getenv('MEMCACHED_HOST'), array('binary_protocol' => false));
22+
23+
return new MemcachedCache($client, str_replace('\\', '.', __CLASS__), $defaultLifetime);
24+
}
25+
}

Traits/MemcachedTrait.php

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,12 @@ protected function doSave(array $values, $lifetime)
198198
$lifetime += time();
199199
}
200200

201-
return $this->checkResultCode($this->getClient()->setMulti($values, $lifetime));
201+
$encodedValues = array();
202+
foreach ($values as $key => $value) {
203+
$encodedValues[rawurlencode($key)] = $value;
204+
}
205+
206+
return $this->checkResultCode($this->getClient()->setMulti($encodedValues, $lifetime));
202207
}
203208

204209
/**
@@ -208,7 +213,16 @@ protected function doFetch(array $ids)
208213
{
209214
$unserializeCallbackHandler = ini_set('unserialize_callback_func', __CLASS__.'::handleUnserializeCallback');
210215
try {
211-
return $this->checkResultCode($this->getClient()->getMulti($ids));
216+
$encodedIds = array_map('rawurlencode', $ids);
217+
218+
$encodedResult = $this->checkResultCode($this->getClient()->getMulti($encodedIds));
219+
220+
$result = array();
221+
foreach ($encodedResult as $key => $value) {
222+
$result[rawurldecode($key)] = $value;
223+
}
224+
225+
return $result;
212226
} catch (\Error $e) {
213227
throw new \ErrorException($e->getMessage(), $e->getCode(), E_ERROR, $e->getFile(), $e->getLine());
214228
} finally {
@@ -221,7 +235,7 @@ protected function doFetch(array $ids)
221235
*/
222236
protected function doHave($id)
223237
{
224-
return false !== $this->getClient()->get($id) || $this->checkResultCode(\Memcached::RES_SUCCESS === $this->client->getResultCode());
238+
return false !== $this->getClient()->get(rawurlencode($id)) || $this->checkResultCode(\Memcached::RES_SUCCESS === $this->client->getResultCode());
225239
}
226240

227241
/**
@@ -230,7 +244,8 @@ protected function doHave($id)
230244
protected function doDelete(array $ids)
231245
{
232246
$ok = true;
233-
foreach ($this->checkResultCode($this->getClient()->deleteMulti($ids)) as $result) {
247+
$encodedIds = array_map('rawurlencode', $ids);
248+
foreach ($this->checkResultCode($this->getClient()->deleteMulti($encodedIds)) as $result) {
234249
if (\Memcached::RES_SUCCESS !== $result && \Memcached::RES_NOTFOUND !== $result) {
235250
$ok = false;
236251
}

0 commit comments

Comments
 (0)