Skip to content

Commit 23b5e64

Browse files
Samantha Quiñonessodabrew
Samantha Quiñones
authored andcommitted
Extended key checking to match the language of the memcached spec (php-memcached-dev#167)
Updated to php7 branch by Aaron Stone <[email protected]>
1 parent 2af9b61 commit 23b5e64

File tree

2 files changed

+97
-17
lines changed

2 files changed

+97
-17
lines changed

php_memcached.c

+26-17
Original file line numberDiff line numberDiff line change
@@ -202,15 +202,28 @@ static inline php_memc_object_t *php_memc_fetch_object(zend_object *obj) {
202202
} \
203203
memc_user_data = (php_memc_user_data_t *) memcached_get_user_data(intern->memc);
204204

205-
#define MEMC_CHECK_KEY(intern, key) \
206-
if (UNEXPECTED(ZSTR_LEN(key) == 0 || \
207-
ZSTR_LEN(key) > MEMC_OBJECT_KEY_MAX_LENGTH || \
208-
(memcached_behavior_get(intern->memc, \
209-
MEMCACHED_BEHAVIOR_BINARY_PROTOCOL) ? \
210-
strchr(ZSTR_VAL(key), '\n') : \
211-
strchr(ZSTR_VAL(key), ' ')))) { \
212-
intern->rescode = MEMCACHED_BAD_KEY_PROVIDED; \
213-
RETURN_FALSE; \
205+
static
206+
zend_bool s_memc_valid_key_binary(const char *key)
207+
{
208+
return strchr(key, '\n') == NULL;
209+
}
210+
211+
static
212+
zend_bool s_memc_valid_key_ascii(const char *key)
213+
{
214+
while (*key && !iscntrl(*key) && !isspace(*key)) ++key;
215+
return *key == '\0';
216+
}
217+
218+
#define MEMC_CHECK_KEY(intern, key) \
219+
if (UNEXPECTED(ZSTR_LEN(key) == 0 || \
220+
ZSTR_LEN(key) > MEMC_OBJECT_KEY_MAX_LENGTH || \
221+
(memcached_behavior_get(intern->memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL) \
222+
? !s_memc_valid_key_binary(ZSTR_VAL(key)) \
223+
: !s_memc_valid_key_ascii(ZSTR_VAL(key)) \
224+
))) { \
225+
intern->rescode = MEMCACHED_BAD_KEY_PROVIDED; \
226+
RETURN_FALSE; \
214227
}
215228

216229
#ifdef HAVE_MEMCACHED_PROTOCOL
@@ -307,18 +320,14 @@ static
307320
PHP_INI_MH(OnUpdateSessionPrefixString)
308321
{
309322
if (new_value && ZSTR_LEN(new_value) > 0) {
310-
char *ptr = ZSTR_VAL(new_value);
311-
312-
while (*ptr != '\0') {
313-
if (isspace (*ptr++)) {
314-
php_error_docref(NULL, E_WARNING, "memcached.sess_prefix cannot contain whitespace characters");
315-
return FAILURE;
316-
}
317-
}
318323
if (ZSTR_LEN(new_value) > MEMCACHED_MAX_KEY) {
319324
php_error_docref(NULL, E_WARNING, "memcached.sess_prefix too long (max: %d)", MEMCACHED_MAX_KEY - 1);
320325
return FAILURE;
321326
}
327+
if (!s_memc_valid_key_ascii(ZSTR_VAL(new_value))) {
328+
php_error_docref(NULL, E_WARNING, "memcached.sess_prefix cannot contain whitespace or control characters");
329+
return FAILURE;
330+
}
322331
}
323332
return OnUpdateString(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage);
324333
}

tests/keys.phpt

+71
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,11 @@ var_dump ($binary->getResultCode () == Memcached::RES_BAD_KEY_PROVIDED);
2828
var_dump ($ascii->set (''/*empty key*/, 'this is a test'));
2929
var_dump ($ascii->getResultCode () == Memcached::RES_BAD_KEY_PROVIDED);
3030

31+
for ($i=0;$i<32;$i++) {
32+
var_dump ($ascii->set ('asciikeywithnonprintablechar-' . chr($i) . '-here', 'this is a test'));
33+
var_dump ($ascii->getResultCode () == Memcached::RES_BAD_KEY_PROVIDED);
34+
}
35+
3136
var_dump ($ascii->set (str_repeat ('1234567890', 512), 'this is a test'));
3237
var_dump ($ascii->getResultCode () == Memcached::RES_BAD_KEY_PROVIDED);
3338

@@ -46,4 +51,70 @@ bool(false)
4651
bool(true)
4752
bool(false)
4853
bool(true)
54+
bool(false)
55+
bool(true)
56+
bool(false)
57+
bool(true)
58+
bool(false)
59+
bool(true)
60+
bool(false)
61+
bool(true)
62+
bool(false)
63+
bool(true)
64+
bool(false)
65+
bool(true)
66+
bool(false)
67+
bool(true)
68+
bool(false)
69+
bool(true)
70+
bool(false)
71+
bool(true)
72+
bool(false)
73+
bool(true)
74+
bool(false)
75+
bool(true)
76+
bool(false)
77+
bool(true)
78+
bool(false)
79+
bool(true)
80+
bool(false)
81+
bool(true)
82+
bool(false)
83+
bool(true)
84+
bool(false)
85+
bool(true)
86+
bool(false)
87+
bool(true)
88+
bool(false)
89+
bool(true)
90+
bool(false)
91+
bool(true)
92+
bool(false)
93+
bool(true)
94+
bool(false)
95+
bool(true)
96+
bool(false)
97+
bool(true)
98+
bool(false)
99+
bool(true)
100+
bool(false)
101+
bool(true)
102+
bool(false)
103+
bool(true)
104+
bool(false)
105+
bool(true)
106+
bool(false)
107+
bool(true)
108+
bool(false)
109+
bool(true)
110+
bool(false)
111+
bool(true)
112+
bool(false)
113+
bool(true)
114+
bool(false)
115+
bool(true)
116+
bool(false)
117+
bool(true)
118+
bool(false)
119+
bool(true)
49120
OK

0 commit comments

Comments
 (0)