Skip to content

Commit 9debfac

Browse files
Samantha Quiñonessodabrew
Samantha Quiñones
authored andcommitted
Extended key checking to match the language of the memcached spec (#167)
Updated to php7 branch by Aaron Stone <aaron@serendipity.cx>
1 parent 2af9b61 commit 9debfac

File tree

4 files changed

+97
-19
lines changed

4 files changed

+97
-19
lines changed

php_memcached.c

Lines changed: 26 additions & 17 deletions
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

Lines changed: 69 additions & 0 deletions
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,68 @@ 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)
49118
OK

tests/session_badconf_emptyprefix.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,5 +24,5 @@ session_write_close();
2424
echo "OK";
2525

2626
--EXPECTF--
27-
Warning: ini_set(): memcached.sess_prefix cannot contain whitespace characters in %s on line %d
27+
Warning: ini_set(): memcached.sess_prefix cannot contain whitespace or control characters in %s on line %d
2828
OK

tests/session_badconf_prefix.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ ini_set('memcached.sess_prefix', str_repeat('a', 512));
1818
echo "OK";
1919

2020
--EXPECTF--
21-
Warning: ini_set(): memcached.sess_prefix cannot contain whitespace characters in %s on line %d
21+
Warning: ini_set(): memcached.sess_prefix cannot contain whitespace or control characters in %s on line %d
2222

2323
Warning: ini_set(): memcached.sess_prefix too long (max: %d) in %s on line %d
2424
OK

0 commit comments

Comments
 (0)