Skip to content

Commit 4908f1c

Browse files
Merge pull request #1 from dennisinteractive/27724_lock_sanitisation
Case 27724; Updated MemcacheBacked lock sanitisation.
2 parents 86475db + a8e8824 commit 4908f1c

File tree

3 files changed

+48
-21
lines changed

3 files changed

+48
-21
lines changed

src/DrupalMemcacheBase.php

Lines changed: 3 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
*/
1515
abstract class DrupalMemcacheBase implements DrupalMemcacheInterface {
1616

17+
use MemcacheCacheNormalizerTrait;
18+
1719
/**
1820
* The memcache config object.
1921
*
@@ -29,13 +31,6 @@ abstract class DrupalMemcacheBase implements DrupalMemcacheInterface {
2931
*/
3032
protected $memcache;
3133

32-
/**
33-
* The hash algorithm to pass to hash(). Defaults to 'sha1'
34-
*
35-
* @var string
36-
*/
37-
protected $hashAlgorithm;
38-
3934
/**
4035
* The prefix memcache key for all keys.
4136
*
@@ -52,7 +47,6 @@ abstract class DrupalMemcacheBase implements DrupalMemcacheInterface {
5247
public function __construct(DrupalMemcacheConfig $settings) {
5348
$this->settings = $settings;
5449

55-
$this->hashAlgorithm = $this->settings->get('key_hash_algorithm', 'sha1');
5650
$this->prefix = $this->settings->get('key_prefix', '');
5751
}
5852

@@ -79,17 +73,7 @@ public function get($key) {
7973
* {@inheritdoc}
8074
*/
8175
public function key($key) {
82-
$full_key = urlencode($this->prefix . '-' . $key);
83-
84-
// Memcache only supports key lengths up to 250 bytes. If we have generated
85-
// a longer key, we shrink it to an acceptable length with a configurable
86-
// hashing algorithm. Sha1 was selected as the default as it performs
87-
// quickly with minimal collisions.
88-
if (strlen($full_key) > 250) {
89-
$full_key = urlencode(hash($this->hashAlgorithm, $this->prefix . '-' . $key));
90-
}
91-
92-
return $full_key;
76+
return $this->normalizeKey($this->prefix . '-' . $key);
9377
}
9478

9579
/**

src/MemcacheBackend.php

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
*/
1818
class MemcacheBackend implements CacheBackendInterface {
1919

20+
use MemcacheCacheNormalizerTrait;
21+
2022
/**
2123
* The cache bin to use.
2224
*
@@ -128,7 +130,7 @@ public function getMultiple(&$cids, $allow_invalid = FALSE) {
128130
* @return bool
129131
*/
130132
protected function valid($cid, \stdClass $cache) {
131-
$lock_key = "memcache_$cid:$this->bin";
133+
$lock_key = $this->normalizeKey("memcache_$cid:$this->bin");
132134
$cache->valid = FALSE;
133135

134136
if ($cache) {
@@ -316,7 +318,7 @@ public function isEmpty() {
316318
* @return string
317319
*/
318320
protected function key($cid) {
319-
return $this->bin . '-' . $cid;
321+
return $this->normalizeKey($this->bin . '-' . $cid);
320322
}
321323

322324
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
<?php
2+
3+
namespace Drupal\memcache;
4+
5+
/**
6+
* Class MemcacheCacheNormalizer.
7+
*/
8+
trait MemcacheCacheNormalizerTrait {
9+
10+
/**
11+
* Normalizes a cache ID in order to comply with key length limitations.
12+
*
13+
* @param string $key
14+
* The passed in cache ID.
15+
*
16+
* @return string
17+
* An ASCII-encoded cache ID that is at most 250 characters long.
18+
*/
19+
protected function normalizeKey($key) {
20+
$key = urlencode($key);
21+
// Nothing to do if the ID is a US ASCII string of 250 characters or less.
22+
$key_is_ascii = mb_check_encoding($key, 'ASCII');
23+
if (strlen($key) <= 250 && $key_is_ascii) {
24+
return $key;
25+
}
26+
// Memcache only supports key lengths up to 250 bytes. If we have generated
27+
// a longer key, we shrink it to an acceptable length with a configurable
28+
// hashing algorithm. Sha1 was selected as the default as it performs
29+
// quickly with minimal collisions.
30+
// Return a string that uses as much as possible of the original cache ID
31+
// with the hash appended.
32+
/** @var DrupalMemcacheConfig $this->settings */
33+
$hash_algorithm = $this->settings->get('key_hash_algorithm', 'sha1');
34+
$hash = hash($hash_algorithm, $key);
35+
if (!$key_is_ascii) {
36+
return $hash;
37+
}
38+
return substr($key, 0, 250 - strlen($hash)) . $hash;
39+
}
40+
41+
}

0 commit comments

Comments
 (0)