Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/phpredis/phpredis.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Grunder <michael.grunder@gmail.com>2020-09-28 21:07:46 +0300
committerGitHub <noreply@github.com>2020-09-28 21:07:46 +0300
commit950e8de807ba17ecfff62504a6ee7a959a5df714 (patch)
treeb74010cca8baeb173be3edf216e66aa3e18b5f83 /library.c
parent7e5191fb5645296b9e852fab7991820c1eaf0422 (diff)
Issue.1847 cluster segfault (#1850)
Fix for #1847 when dealing with NULL multi bulk replies in RedisCluster. Adds `Redis::OPT_NULL_MULTIBULK_AS_NULL` setting to have PhpRedis treat NULL multi bulk replies as `NULL` instead of `[]`. Co-authored-by: Alex Offshore <offshore@aopdg.ru>
Diffstat (limited to 'library.c')
-rw-r--r--library.c62
1 files changed, 39 insertions, 23 deletions
diff --git a/library.c b/library.c
index 6aef6274..2648c565 100644
--- a/library.c
+++ b/library.c
@@ -1600,10 +1600,13 @@ redis_xread_reply(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
if (read_mbulk_header(redis_sock, &streams) < 0)
goto failure;
- array_init(&z_rv);
-
- if (redis_read_stream_messages_multi(redis_sock, streams, &z_rv) < 0)
- goto cleanup;
+ if (streams == -1 && redis_sock->null_mbulk_as_null) {
+ ZVAL_NULL(&z_rv);
+ } else {
+ array_init(&z_rv);
+ if (redis_read_stream_messages_multi(redis_sock, streams, &z_rv) < 0)
+ goto cleanup;
+ }
if (IS_ATOMIC(redis_sock)) {
RETVAL_ZVAL(&z_rv, 0, 1);
@@ -2427,6 +2430,7 @@ PHP_REDIS_API int redis_sock_read_multibulk_reply(INTERNAL_FUNCTION_PARAMETERS,
RedisSock *redis_sock, zval *z_tab,
void *ctx)
{
+ zval z_multi_result;
char inbuf[4096];
int numElems;
size_t len;
@@ -2448,10 +2452,13 @@ PHP_REDIS_API int redis_sock_read_multibulk_reply(INTERNAL_FUNCTION_PARAMETERS,
}
numElems = atoi(inbuf+1);
- zval z_multi_result;
- array_init(&z_multi_result); /* pre-allocate array for multi's results. */
- redis_mbulk_reply_loop(redis_sock, &z_multi_result, numElems, UNSERIALIZE_ALL);
+ if (numElems == -1 && redis_sock->null_mbulk_as_null) {
+ ZVAL_NULL(&z_multi_result);
+ } else {
+ array_init(&z_multi_result);
+ redis_mbulk_reply_loop(redis_sock, &z_multi_result, numElems, UNSERIALIZE_ALL);
+ }
if (IS_ATOMIC(redis_sock)) {
RETVAL_ZVAL(&z_multi_result, 0, 1);
@@ -2459,7 +2466,6 @@ PHP_REDIS_API int redis_sock_read_multibulk_reply(INTERNAL_FUNCTION_PARAMETERS,
add_next_index_zval(z_tab, &z_multi_result);
}
- /*zval_copy_ctor(return_value); */
return 0;
}
@@ -3231,7 +3237,7 @@ redis_read_variant_bulk(RedisSock *redis_sock, int size, zval *z_ret
}
PHP_REDIS_API int
-redis_read_multibulk_recursive(RedisSock *redis_sock, int elements, int status_strings,
+redis_read_multibulk_recursive(RedisSock *redis_sock, long long elements, int status_strings,
zval *z_ret)
{
long reply_info;
@@ -3267,11 +3273,15 @@ redis_read_multibulk_recursive(RedisSock *redis_sock, int elements, int status_s
add_next_index_zval(z_ret, &z_subelem);
break;
case TYPE_MULTIBULK:
- // Construct an array for our sub element, and add it, and recurse
- array_init(&z_subelem);
- add_next_index_zval(z_ret, &z_subelem);
- redis_read_multibulk_recursive(redis_sock, reply_info, status_strings,
- &z_subelem);
+ if (reply_info < 0 && redis_sock->null_mbulk_as_null) {
+ add_next_index_null(z_ret);
+ } else {
+ array_init(&z_subelem);
+ if (reply_info > 0) {
+ redis_read_multibulk_recursive(redis_sock, reply_info, status_strings, &z_subelem);
+ }
+ add_next_index_zval(z_ret, &z_subelem);
+ }
break;
default:
// Stop the compiler from whinging
@@ -3287,7 +3297,8 @@ redis_read_multibulk_recursive(RedisSock *redis_sock, int elements, int status_s
static int
variant_reply_generic(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
- int status_strings, zval *z_tab, void *ctx)
+ int status_strings, int null_mbulk_as_null,
+ zval *z_tab, void *ctx)
{
// Reply type, and reply size vars
REDIS_REPLY_TYPE reply_type;
@@ -3312,13 +3323,15 @@ variant_reply_generic(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
redis_read_variant_bulk(redis_sock, reply_info, &z_ret);
break;
case TYPE_MULTIBULK:
- /* Initialize an array for our multi-bulk response */
- array_init(&z_ret);
-
- // If we've got more than zero elements, parse our multi bulk
- // response recursively
if (reply_info > -1) {
+ array_init(&z_ret);
redis_read_multibulk_recursive(redis_sock, reply_info, status_strings, &z_ret);
+ } else {
+ if (null_mbulk_as_null) {
+ ZVAL_NULL(&z_ret);
+ } else {
+ array_init(&z_ret);
+ }
}
break;
default:
@@ -3343,21 +3356,24 @@ redis_read_raw_variant_reply(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock
zval *z_tab, void *ctx)
{
return variant_reply_generic(INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock,
- redis_sock->reply_literal, z_tab, ctx);
+ redis_sock->reply_literal,
+ redis_sock->null_mbulk_as_null,
+ z_tab, ctx);
}
PHP_REDIS_API int
redis_read_variant_reply(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
zval *z_tab, void *ctx)
{
- return variant_reply_generic(INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock, 0, z_tab, ctx);
+ return variant_reply_generic(INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock, 0,
+ redis_sock->null_mbulk_as_null, z_tab, ctx);
}
PHP_REDIS_API int
redis_read_variant_reply_strings(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
zval *z_tab, void *ctx)
{
- return variant_reply_generic(INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock, 1, z_tab, ctx);
+ return variant_reply_generic(INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock, 1, 0, z_tab, ctx);
}
PHP_REDIS_API