@@ -422,6 +422,7 @@ static void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key)
422422 uint32_t dummy_flags ;
423423 int rc ;
424424 memcached_return dummy_status ;
425+ bool return_value_set = false;
425426
426427 status = memcached_mget_by_key (i_obj -> memc , server_key , server_key_len , & key , & key_len , 1 );
427428 payload = memcached_fetch (i_obj -> memc , NULL , NULL , & payload_len , & flags , & status );
@@ -432,10 +433,12 @@ static void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key)
432433 /*
433434 * If payload wasn't found and we have a read-through callback, invoke it to get
434435 * the value. The callback will take care of storing the value back into memcache.
436+ * The callback will set the return value.
435437 */
436438 if (payload == NULL && status == MEMCACHED_NOTFOUND && fci .size != 0 ) {
437439 status = php_memc_do_cache_callback (getThis (), & fci , & fcc , key , key_len ,
438440 return_value TSRMLS_CC );
441+ return_value_set = true;
439442 }
440443
441444 (void )memcached_fetch (i_obj -> memc , NULL , NULL , & dummy_length , & dummy_flags , & dummy_status );
@@ -447,8 +450,8 @@ static void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key)
447450 RETURN_FALSE ;
448451 }
449452
450- /* payload will be NULL if the callback was invoked */
451- if (payload != NULL ) {
453+ /* if memcached gave a value and there was no callback, payload may be NULL */
454+ if (! return_value_set ) {
452455 rc = php_memc_zval_from_payload (return_value , payload , payload_len , flags TSRMLS_CC );
453456 free (payload );
454457 if (rc < 0 ) {
@@ -1954,7 +1957,6 @@ static char *php_memc_zval_to_payload(zval *value, size_t *payload_len, uint32_t
19541957 } else {
19551958#endif
19561959 php_serialize_data_t var_hash ;
1957-
19581960 PHP_VAR_SERIALIZE_INIT (var_hash );
19591961 php_var_serialize (& buf , & value , & var_hash TSRMLS_CC );
19601962 PHP_VAR_SERIALIZE_DESTROY (var_hash );
@@ -2004,8 +2006,16 @@ static char *php_memc_zval_to_payload(zval *value, size_t *payload_len, uint32_t
20042006
20052007static int php_memc_zval_from_payload (zval * value , char * payload , size_t payload_len , uint32_t flags TSRMLS_DC )
20062008{
2007- if (payload == NULL ) {
2009+ /*
2010+ A NULL payload is completely valid if length is 0, it is simply empty.
2011+ */
2012+ char dummy_payload [1 ] = { 0 };
2013+ if (payload == NULL && payload_len > 0 ) {
2014+ php_error_docref (NULL TSRMLS_CC , E_WARNING ,
2015+ "Could not handle non-existing value of length %zu" , payload_len );
20082016 return -1 ;
2017+ } else if (payload == NULL ) {
2018+ payload = dummy_payload ;
20092019 }
20102020
20112021 if (flags & MEMC_VAL_COMPRESSED ) {
@@ -2084,8 +2094,7 @@ static int php_memc_zval_from_payload(zval *value, char *payload, size_t payload
20842094 double dval = zend_strtod (payload , NULL );
20852095 ZVAL_DOUBLE (value , dval );
20862096 } else if (flags & MEMC_VAL_IS_BOOL ) {
2087- long bval = strtol (payload , NULL , 10 );
2088- ZVAL_BOOL (value , bval );
2097+ ZVAL_BOOL (value , payload_len > 0 && payload [0 ] == '1' );
20892098 } else {
20902099 ZVAL_STRINGL (value , payload , payload_len , 1 );
20912100 }
0 commit comments