Skip to content

Commit 40c2c60

Browse files
author
Mikko Koppanen
committed
Merge pull request #84 from mkoppanen/master
A bit of general maintenance, mainly related to issue #69
2 parents 06f6ae3 + 29e5d83 commit 40c2c60

File tree

4 files changed

+78
-72
lines changed

4 files changed

+78
-72
lines changed

php_memcached.c

Lines changed: 72 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -311,7 +311,7 @@ PHP_INI_END()
311311
****************************************/
312312
static int php_memc_handle_error(php_memc_t *i_obj, memcached_return status TSRMLS_DC);
313313
static char *php_memc_zval_to_payload(zval *value, size_t *payload_len, uint32_t *flags, enum memcached_serializer serializer, enum memcached_compression_type compression_type TSRMLS_DC);
314-
static int php_memc_zval_from_payload(zval *value, char *payload, size_t payload_len, uint32_t flags, enum memcached_serializer serializer TSRMLS_DC);
314+
static int php_memc_zval_from_payload(zval *value, const char *payload, size_t payload_len, uint32_t flags, enum memcached_serializer serializer TSRMLS_DC);
315315
static void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key);
316316
static void php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key);
317317
static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool by_key);
@@ -321,9 +321,14 @@ static void php_memc_deleteMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by
321321
static void php_memc_getDelayed_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key);
322322
static memcached_return php_memc_do_cache_callback(zval *memc_obj, zend_fcall_info *fci, zend_fcall_info_cache *fcc, char *key, size_t key_len, zval *value TSRMLS_DC);
323323
static int php_memc_do_result_callback(zval *memc_obj, zend_fcall_info *fci, zend_fcall_info_cache *fcc, memcached_result_st *result TSRMLS_DC);
324-
static memcached_return php_memc_do_serverlist_callback(const memcached_st *ptr, memcached_server_instance_st instance, void *in_context);
325-
static memcached_return php_memc_do_stats_callback(const memcached_st *ptr, memcached_server_instance_st instance, void *in_context);
326-
static memcached_return php_memc_do_version_callback(const memcached_st *ptr, memcached_server_instance_st instance, void *in_context);
324+
325+
// Cursor callbacks
326+
static memcached_return php_memc_do_serverlist_callback(const memcached_st *ptr, const memcached_instance_st *instance, void *in_context);
327+
static memcached_return php_memc_do_stats_callback(const memcached_st *ptr, const memcached_instance_st *instance, void *in_context);
328+
static memcached_return php_memc_do_version_callback(const memcached_st *ptr, const memcached_instance_st *instance, void *in_context);
329+
330+
331+
327332
static void php_memc_destroy(struct memc_obj *m_obj, zend_bool persistent TSRMLS_DC);
328333

329334
/****************************************
@@ -514,7 +519,6 @@ static void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key)
514519
int key_len = 0;
515520
char *server_key = NULL;
516521
int server_key_len = 0;
517-
char *payload = NULL;
518522
size_t payload_len = 0;
519523
uint32_t flags = 0;
520524
uint64_t cas = 0;
@@ -551,6 +555,7 @@ static void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key)
551555
key_lens[0] = key_len;
552556

553557
if (cas_token) {
558+
const char *payload = NULL;
554559
uint64_t orig_cas_flag;
555560

556561
/*
@@ -619,6 +624,7 @@ static void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key)
619624
memcached_result_free(&result);
620625

621626
} else {
627+
char *payload = NULL;
622628
int rc;
623629
zend_bool return_value_set = 0;
624630

@@ -691,11 +697,11 @@ static void php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke
691697
int server_key_len = 0;
692698
size_t num_keys = 0;
693699
zval **entry = NULL;
694-
char *payload = NULL;
700+
const char *payload = NULL;
695701
size_t payload_len = 0;
696702
const char **mkeys = NULL;
697703
size_t *mkeys_len = NULL;
698-
char *res_key = NULL;
704+
const char *res_key = NULL;
699705
size_t res_key_len = 0;
700706
uint32_t flags;
701707
uint64_t cas = 0;
@@ -806,12 +812,6 @@ static void php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke
806812
res_key = memcached_result_key_value(&result);
807813
res_key_len = memcached_result_key_length(&result);
808814

809-
/*
810-
* This may be a bug in libmemcached, the key is not null terminated
811-
* whe using the binary protocol.
812-
*/
813-
res_key[res_key_len] = 0;
814-
815815
MAKE_STD_ZVAL(value);
816816

817817
if (php_memc_zval_from_payload(value, payload, payload_len, flags, m_obj->serializer TSRMLS_CC) < 0) {
@@ -829,7 +829,21 @@ static void php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke
829829
continue;
830830
}
831831

832-
add_assoc_zval_ex(return_value, res_key, res_key_len+1, value);
832+
if (res_key [res_key_len - 1] != '\0') {
833+
/* Terminate if needed */
834+
char key_buffer [MEMCACHED_MAX_KEY];
835+
836+
if (res_key_len < MEMCACHED_MAX_KEY) {
837+
memcpy (key_buffer, res_key, res_key_len);
838+
key_buffer [res_key_len] = '\0';
839+
840+
add_assoc_zval_ex(return_value, key_buffer, res_key_len + 1, value);
841+
}
842+
}
843+
else {
844+
add_assoc_zval_ex(return_value, res_key, res_key_len + 1, value);
845+
}
846+
833847
if (cas_tokens) {
834848
cas = memcached_result_cas(&result);
835849
add_assoc_double_ex(cas_tokens, res_key, res_key_len+1, (double)cas);
@@ -992,9 +1006,9 @@ static void php_memc_getDelayed_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_
9921006
Returns the next result from a previous delayed request */
9931007
PHP_METHOD(Memcached, fetch)
9941008
{
995-
char *res_key = NULL;
1009+
const char *res_key = NULL;
9961010
size_t res_key_len = 0;
997-
char *payload = NULL;
1011+
const char *payload = NULL;
9981012
size_t payload_len = 0;
9991013
zval *value;
10001014
uint32_t flags = 0;
@@ -1049,9 +1063,9 @@ PHP_METHOD(Memcached, fetch)
10491063
Returns all the results from a previous delayed request */
10501064
PHP_METHOD(Memcached, fetchAll)
10511065
{
1052-
char *res_key = NULL;
1066+
const char *res_key = NULL;
10531067
size_t res_key_len = 0;
1054-
char *payload = NULL;
1068+
const char *payload = NULL;
10551069
size_t payload_len = 0;
10561070
zval *value, *entry;
10571071
uint32_t flags;
@@ -1965,7 +1979,7 @@ PHP_METHOD(Memcached, getServerByKey)
19651979
{
19661980
char *server_key;
19671981
int server_key_len;
1968-
memcached_server_instance_st *server_instance;
1982+
const memcached_instance_st *server_instance;
19691983
memcached_return error;
19701984
MEMC_METHOD_INIT_VARS;
19711985

@@ -2083,7 +2097,7 @@ PHP_METHOD(Memcached, getLastErrorErrno)
20832097
Was added in 0.34 according to libmemcached's Changelog */
20842098
PHP_METHOD(Memcached, getLastDisconnectedServer)
20852099
{
2086-
memcached_server_instance_st *server_instance;
2100+
const memcached_instance_st *server_instance;
20872101
MEMC_METHOD_INIT_VARS;
20882102

20892103
if (zend_parse_parameters_none() == FAILURE) {
@@ -2398,12 +2412,7 @@ static int php_memc_set_option(php_memc_t *i_obj, long option, zval *value TSRML
23982412
*/
23992413
flag = (memcached_behavior) option;
24002414
convert_to_long(value);
2401-
if (flag < 0 ||
2402-
/* MEMCACHED_BEHAVIOR_MAX was added in somewhere around 0.36 or 0.37 */
2403-
#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX >= 0x00037000
2404-
flag >= MEMCACHED_BEHAVIOR_MAX ||
2405-
#endif
2406-
memcached_behavior_set(m_obj->memc, flag, (uint64_t)Z_LVAL_P(value)) != MEMCACHED_SUCCESS) {
2415+
if (memcached_behavior_set(m_obj->memc, flag, (uint64_t) Z_LVAL_P(value)) != MEMCACHED_SUCCESS) {
24072416
php_error_docref(NULL TSRMLS_CC, E_WARNING, "error setting memcached option");
24082417
return 0;
24092418
}
@@ -2660,7 +2669,7 @@ ZEND_RSRC_DTOR_FUNC(php_memc_sess_dtor)
26602669
/* }}} */
26612670

26622671
/* {{{ internal API functions */
2663-
static memcached_return php_memc_do_serverlist_callback(const memcached_st *ptr, memcached_server_instance_st instance, void *in_context)
2672+
static memcached_return php_memc_do_serverlist_callback(const memcached_st *ptr, const memcached_instance_st *instance, void *in_context)
26642673
{
26652674
struct callbackContext* context = (struct callbackContext*) in_context;
26662675
zval *array;
@@ -2671,14 +2680,17 @@ static memcached_return php_memc_do_serverlist_callback(const memcached_st *ptr,
26712680
add_assoc_long(array, "port", memcached_server_port(instance));
26722681
/*
26732682
* API does not allow to get at this field.
2683+
*
2684+
* If you comment out stuff like this, please fix tests. -- Mikko
2685+
*
26742686
add_assoc_long(array, "weight", instance->weight);
26752687
*/
26762688

26772689
add_next_index_zval(context->return_value, array);
26782690
return MEMCACHED_SUCCESS;
26792691
}
26802692

2681-
static memcached_return php_memc_do_stats_callback(const memcached_st *ptr, memcached_server_instance_st instance, void *in_context)
2693+
static memcached_return php_memc_do_stats_callback(const memcached_st *ptr, const memcached_instance_st *instance, void *in_context)
26822694
{
26832695
char *hostport = NULL;
26842696
int hostport_len;
@@ -2722,7 +2734,7 @@ static memcached_return php_memc_do_stats_callback(const memcached_st *ptr, memc
27222734
return MEMCACHED_SUCCESS;
27232735
}
27242736

2725-
static memcached_return php_memc_do_version_callback(const memcached_st *ptr, memcached_server_instance_st instance, void *in_context)
2737+
static memcached_return php_memc_do_version_callback(const memcached_st *ptr, const memcached_instance_st *instance, void *in_context)
27262738
{
27272739
char *hostport = NULL;
27282740
char version[16];
@@ -2953,19 +2965,26 @@ static char *php_memc_zval_to_payload(zval *value, size_t *payload_len, uint32_t
29532965
}
29542966

29552967
/* The caller MUST free the payload */
2956-
static int php_memc_zval_from_payload(zval *value, char *payload, size_t payload_len, uint32_t flags, enum memcached_serializer serializer TSRMLS_DC)
2968+
static int php_memc_zval_from_payload(zval *value, const char *payload, size_t payload_len, uint32_t flags, enum memcached_serializer serializer TSRMLS_DC)
29572969
{
2970+
char *pl;
2971+
size_t pl_len;
2972+
29582973
/*
29592974
A NULL payload is completely valid if length is 0, it is simply empty.
29602975
*/
29612976
zend_bool payload_emalloc = 0;
2962-
char *buffer = NULL;
29632977

2964-
if (payload == NULL && payload_len > 0) {
2978+
// Explicit cast
2979+
pl = (char *) payload;
2980+
pl_len = payload_len;
2981+
2982+
2983+
if (pl == NULL && pl_len > 0) {
29652984
php_error_docref(NULL TSRMLS_CC, E_WARNING,
2966-
"Could not handle non-existing value of length %zu", payload_len);
2985+
"Could not handle non-existing value of length %zu", pl_len);
29672986
return -1;
2968-
} else if (payload == NULL) {
2987+
} else if (pl == NULL) {
29692988
if (MEMC_VAL_GET_TYPE(flags) == MEMC_VAL_IS_BOOL) {
29702989
ZVAL_FALSE(value);
29712990
} else {
@@ -2976,6 +2995,7 @@ static int php_memc_zval_from_payload(zval *value, char *payload, size_t payload
29762995

29772996
if (flags & MEMC_VAL_COMPRESSED) {
29782997
uint32_t len;
2998+
char *buffer = NULL;
29792999
unsigned long length;
29803000
zend_bool decompress_status = 0;
29813001

@@ -3017,49 +3037,47 @@ static int php_memc_zval_from_payload(zval *value, char *payload, size_t payload
30173037
efree(buffer);
30183038
return -1;
30193039
}
3020-
payload = buffer;
3021-
payload_len = length;
3040+
pl = buffer;
3041+
pl_len = length;
30223042
payload_emalloc = 1;
30233043
}
30243044

3025-
payload[payload_len] = 0;
3026-
30273045
switch (MEMC_VAL_GET_TYPE(flags)) {
30283046
case MEMC_VAL_IS_STRING:
30293047
if (payload_emalloc) {
3030-
ZVAL_STRINGL(value, payload, payload_len, 0);
3048+
ZVAL_STRINGL(value, pl, pl_len, 0);
30313049
payload_emalloc = 0;
30323050
} else {
3033-
ZVAL_STRINGL(value, payload, payload_len, 1);
3051+
ZVAL_STRINGL(value, pl, pl_len, 1);
30343052
}
30353053
break;
30363054

30373055
case MEMC_VAL_IS_LONG:
30383056
{
3039-
long lval = strtol(payload, NULL, 10);
3057+
long lval = strtol(pl, NULL, 10);
30403058
ZVAL_LONG(value, lval);
30413059
break;
30423060
}
30433061

30443062
case MEMC_VAL_IS_DOUBLE:
3045-
if (payload_len == 8 && memcmp(payload, "Infinity", 8) == 0) {
3063+
if (pl_len == 8 && memcmp(pl, "Infinity", 8) == 0) {
30463064
ZVAL_DOUBLE(value, php_get_inf());
3047-
} else if (payload_len == 9 && memcmp(payload, "-Infinity", 9) == 0) {
3065+
} else if (pl_len == 9 && memcmp(pl, "-Infinity", 9) == 0) {
30483066
ZVAL_DOUBLE(value, -php_get_inf());
3049-
} else if (payload_len == 3 && memcmp(payload, "NaN", 3) == 0) {
3067+
} else if (pl_len == 3 && memcmp(pl, "NaN", 3) == 0) {
30503068
ZVAL_DOUBLE(value, php_get_nan());
30513069
} else {
3052-
ZVAL_DOUBLE(value, zend_strtod(payload, NULL));
3070+
ZVAL_DOUBLE(value, zend_strtod(pl, NULL));
30533071
}
30543072
break;
30553073

30563074
case MEMC_VAL_IS_BOOL:
3057-
ZVAL_BOOL(value, payload_len > 0 && payload[0] == '1');
3075+
ZVAL_BOOL(value, pl_len > 0 && pl[0] == '1');
30583076
break;
30593077

30603078
case MEMC_VAL_IS_SERIALIZED:
30613079
{
3062-
const char *payload_tmp = payload;
3080+
const char *payload_tmp = pl;
30633081
php_unserialize_data_t var_hash;
30643082

30653083
PHP_VAR_UNSERIALIZE_INIT(var_hash);
@@ -3075,7 +3093,7 @@ static int php_memc_zval_from_payload(zval *value, char *payload, size_t payload
30753093

30763094
case MEMC_VAL_IS_IGBINARY:
30773095
#ifdef HAVE_MEMCACHED_IGBINARY
3078-
if (igbinary_unserialize((uint8_t *)payload, payload_len, &value TSRMLS_CC)) {
3096+
if (igbinary_unserialize((uint8_t *)pl, pl_len, &value TSRMLS_CC)) {
30793097
ZVAL_FALSE(value);
30803098
php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not unserialize value with igbinary");
30813099
goto my_error;
@@ -3089,9 +3107,9 @@ static int php_memc_zval_from_payload(zval *value, char *payload, size_t payload
30893107
case MEMC_VAL_IS_JSON:
30903108
#ifdef HAVE_JSON_API
30913109
# if HAVE_JSON_API_5_2
3092-
php_json_decode(value, payload, payload_len, (serializer == SERIALIZER_JSON_ARRAY) TSRMLS_CC);
3110+
php_json_decode(value, pl, pl_len, (serializer == SERIALIZER_JSON_ARRAY) TSRMLS_CC);
30933111
# elif HAVE_JSON_API_5_3
3094-
php_json_decode(value, payload, payload_len, (serializer == SERIALIZER_JSON_ARRAY), JSON_PARSER_DEFAULT_DEPTH TSRMLS_CC);
3112+
php_json_decode(value, pl, pl_len, (serializer == SERIALIZER_JSON_ARRAY), JSON_PARSER_DEFAULT_DEPTH TSRMLS_CC);
30953113
# endif
30963114
#else
30973115
php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not unserialize value, no json support");
@@ -3105,14 +3123,14 @@ static int php_memc_zval_from_payload(zval *value, char *payload, size_t payload
31053123
}
31063124

31073125
if (payload_emalloc) {
3108-
efree(payload);
3126+
efree(pl);
31093127
}
31103128

31113129
return 0;
31123130

31133131
my_error:
31143132
if (payload_emalloc) {
3115-
efree(payload);
3133+
efree(pl);
31163134
}
31173135
return -1;
31183136
}
@@ -3269,9 +3287,9 @@ static int php_memc_do_result_callback(zval *zmemc_obj, zend_fcall_info *fci,
32693287
zend_fcall_info_cache *fcc,
32703288
memcached_result_st *result TSRMLS_DC)
32713289
{
3272-
char *res_key = NULL;
3290+
const char *res_key = NULL;
32733291
size_t res_key_len = 0;
3274-
char *payload = NULL;
3292+
const char *payload = NULL;
32753293
size_t payload_len = 0;
32763294
zval *value, *retval = NULL;
32773295
uint64_t cas = 0;

tests/bug_16084.phpt

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,10 @@ var_dump($m->getServerList());
1313
bool(true)
1414
array(1) {
1515
[0]=>
16-
array(3) {
16+
array(2) {
1717
["host"]=>
1818
string(9) "localhost"
1919
["port"]=>
2020
int(11211)
21-
["weight"]=>
22-
int(3)
2321
}
2422
}

0 commit comments

Comments
 (0)