@@ -61,7 +61,7 @@ static void dump_reply(clusterReply *reply, int indent) {
61
61
smart_string_appendl(&buf, "\"", 1);
62
62
break;
63
63
case TYPE_MULTIBULK:
64
- if (reply->elements == (size_t)-1 ) {
64
+ if (reply->elements < 0 ) {
65
65
smart_string_appendl(&buf, "(nil)", sizeof("(nil)")-1);
66
66
} else {
67
67
for (i = 0; i < reply->elements; i++) {
@@ -91,7 +91,7 @@ static void dump_reply(clusterReply *reply, int indent) {
91
91
/* Recursively free our reply object. If free_data is non-zero we'll also free
92
92
* the payload data (strings) themselves. If not, we just free the structs */
93
93
void cluster_free_reply (clusterReply * reply , int free_data ) {
94
- int i ;
94
+ long long i ;
95
95
96
96
switch (reply -> type ) {
97
97
case TYPE_ERR :
@@ -101,10 +101,14 @@ void cluster_free_reply(clusterReply *reply, int free_data) {
101
101
efree (reply -> str );
102
102
break ;
103
103
case TYPE_MULTIBULK :
104
- for (i = 0 ; i < reply -> elements && reply -> element [i ]; i ++ ) {
105
- cluster_free_reply (reply -> element [i ], free_data );
104
+ if (reply -> element ) {
105
+ if (reply -> elements > 0 ) {
106
+ for (i = 0 ; i < reply -> elements && reply -> element [i ]; i ++ ) {
107
+ cluster_free_reply (reply -> element [i ], free_data );
108
+ }
109
+ }
110
+ efree (reply -> element );
106
111
}
107
- if (reply -> element ) efree (reply -> element );
108
112
break ;
109
113
default :
110
114
break ;
@@ -154,13 +158,11 @@ cluster_multibulk_resp_recursive(RedisSock *sock, size_t elements,
154
158
}
155
159
break ;
156
160
case TYPE_MULTIBULK :
157
- if (r -> len >= 0 ) {
158
- r -> elements = r -> len ;
159
- if (r -> len > 0 ) {
160
- r -> element = ecalloc (r -> len ,sizeof (clusterReply * ));
161
- if (cluster_multibulk_resp_recursive (sock , r -> elements , r -> element , status_strings ) < 0 ) {
162
- return FAILURE ;
163
- }
161
+ r -> elements = r -> len ;
162
+ if (r -> elements > 0 ) {
163
+ r -> element = ecalloc (r -> len , sizeof (* r -> element ));
164
+ if (cluster_multibulk_resp_recursive (sock , r -> elements , r -> element , status_strings ) < 0 ) {
165
+ return FAILURE ;
164
166
}
165
167
}
166
168
break ;
@@ -204,7 +206,7 @@ clusterReply *cluster_read_resp(redisCluster *c, int status_strings) {
204
206
* command and consumed the reply type and meta info (length) */
205
207
clusterReply *
206
208
cluster_read_sock_resp (RedisSock * redis_sock , REDIS_REPLY_TYPE type ,
207
- char * line_reply , size_t len )
209
+ char * line_reply , long long len )
208
210
{
209
211
clusterReply * r ;
210
212
@@ -232,7 +234,7 @@ cluster_read_sock_resp(RedisSock *redis_sock, REDIS_REPLY_TYPE type,
232
234
break ;
233
235
case TYPE_MULTIBULK :
234
236
r -> elements = len ;
235
- if (len != ( size_t ) -1 ) {
237
+ if (r -> elements > 0 ) {
236
238
r -> element = ecalloc (len , sizeof (clusterReply * ));
237
239
if (cluster_multibulk_resp_recursive (redis_sock , len , r -> element , line_reply != NULL ) < 0 ) {
238
240
cluster_free_reply (r , 1 );
@@ -241,7 +243,7 @@ cluster_read_sock_resp(RedisSock *redis_sock, REDIS_REPLY_TYPE type,
241
243
}
242
244
break ;
243
245
default :
244
- cluster_free_reply (r ,1 );
246
+ cluster_free_reply (r , 1 );
245
247
return NULL ;
246
248
}
247
249
@@ -1939,10 +1941,11 @@ PHP_REDIS_API void cluster_unsub_resp(INTERNAL_FUNCTION_PARAMETERS,
1939
1941
}
1940
1942
1941
1943
/* Recursive MULTI BULK -> PHP style response handling */
1942
- static void cluster_mbulk_variant_resp (clusterReply * r , zval * z_ret )
1944
+ static void cluster_mbulk_variant_resp (clusterReply * r , int null_mbulk_as_null ,
1945
+ zval * z_ret )
1943
1946
{
1944
1947
zval z_sub_ele ;
1945
- int i ;
1948
+ long long i ;
1946
1949
1947
1950
switch (r -> type ) {
1948
1951
case TYPE_INT :
@@ -1963,11 +1966,15 @@ static void cluster_mbulk_variant_resp(clusterReply *r, zval *z_ret)
1963
1966
}
1964
1967
break ;
1965
1968
case TYPE_MULTIBULK :
1966
- array_init (& z_sub_ele );
1967
- for (i = 0 ; i < r -> elements ; i ++ ) {
1968
- cluster_mbulk_variant_resp (r -> element [i ], & z_sub_ele );
1969
+ if (r -> elements < 0 && null_mbulk_as_null ) {
1970
+ add_next_index_null (z_ret );
1971
+ } else {
1972
+ array_init (& z_sub_ele );
1973
+ for (i = 0 ; i < r -> elements ; i ++ ) {
1974
+ cluster_mbulk_variant_resp (r -> element [i ], null_mbulk_as_null , & z_sub_ele );
1975
+ }
1976
+ add_next_index_zval (z_ret , & z_sub_ele );
1969
1977
}
1970
- add_next_index_zval (z_ret , & z_sub_ele );
1971
1978
break ;
1972
1979
default :
1973
1980
add_next_index_bool (z_ret , 0 );
@@ -1983,7 +1990,7 @@ cluster_variant_resp_generic(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c,
1983
1990
{
1984
1991
clusterReply * r ;
1985
1992
zval zv , * z_arr = & zv ;
1986
- int i ;
1993
+ long long i ;
1987
1994
1988
1995
// Make sure we can read it
1989
1996
if ((r = cluster_read_resp (c , status_strings )) == NULL ) {
@@ -2014,12 +2021,15 @@ cluster_variant_resp_generic(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c,
2014
2021
}
2015
2022
break ;
2016
2023
case TYPE_MULTIBULK :
2017
- array_init (z_arr );
2018
-
2019
- for (i = 0 ; i < r -> elements ; i ++ ) {
2020
- cluster_mbulk_variant_resp (r -> element [i ], z_arr );
2024
+ if (r -> elements < 0 && c -> flags -> null_mbulk_as_null ) {
2025
+ RETVAL_NULL ();
2026
+ } else {
2027
+ array_init (z_arr );
2028
+ for (i = 0 ; i < r -> elements ; i ++ ) {
2029
+ cluster_mbulk_variant_resp (r -> element [i ], c -> flags -> null_mbulk_as_null , z_arr );
2030
+ }
2031
+ RETVAL_ZVAL (z_arr , 0 , 0 );
2021
2032
}
2022
- RETVAL_ZVAL (z_arr , 0 , 0 );
2023
2033
break ;
2024
2034
default :
2025
2035
RETVAL_FALSE ;
@@ -2048,7 +2058,11 @@ cluster_variant_resp_generic(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c,
2048
2058
}
2049
2059
break ;
2050
2060
case TYPE_MULTIBULK :
2051
- cluster_mbulk_variant_resp (r , & c -> multi_resp );
2061
+ if (r -> elements < 0 && c -> flags -> null_mbulk_as_null ) {
2062
+ add_next_index_null (& c -> multi_resp );
2063
+ } else {
2064
+ cluster_mbulk_variant_resp (r , c -> flags -> null_mbulk_as_null , & c -> multi_resp );
2065
+ }
2052
2066
break ;
2053
2067
default :
2054
2068
add_next_index_bool (& c -> multi_resp , 0 );
@@ -2069,7 +2083,8 @@ PHP_REDIS_API void cluster_variant_resp(INTERNAL_FUNCTION_PARAMETERS, redisClust
2069
2083
PHP_REDIS_API void cluster_variant_raw_resp (INTERNAL_FUNCTION_PARAMETERS , redisCluster * c ,
2070
2084
void * ctx )
2071
2085
{
2072
- cluster_variant_resp_generic (INTERNAL_FUNCTION_PARAM_PASSTHRU , c , c -> flags -> reply_literal , ctx );
2086
+ cluster_variant_resp_generic (INTERNAL_FUNCTION_PARAM_PASSTHRU , c ,
2087
+ c -> flags -> reply_literal , ctx );
2073
2088
}
2074
2089
2075
2090
PHP_REDIS_API void cluster_variant_resp_strings (INTERNAL_FUNCTION_PARAMETERS , redisCluster * c ,
@@ -2084,23 +2099,25 @@ PHP_REDIS_API void cluster_gen_mbulk_resp(INTERNAL_FUNCTION_PARAMETERS,
2084
2099
{
2085
2100
zval z_result ;
2086
2101
2087
- /* Return FALSE if we didn 't get a multi-bulk response */
2088
- if (c -> reply_type != TYPE_MULTIBULK ) {
2102
+ /* Abort if the reply isn 't MULTIBULK or has an invalid length */
2103
+ if (c -> reply_type != TYPE_MULTIBULK || c -> reply_len < -1 ) {
2089
2104
CLUSTER_RETURN_FALSE (c );
2090
2105
}
2091
2106
2092
- /* Allocate our array */
2093
- array_init (& z_result );
2107
+ if (c -> reply_len == -1 && c -> flags -> null_mbulk_as_null ) {
2108
+ ZVAL_NULL (& z_result );
2109
+ } else {
2110
+ array_init (& z_result );
2094
2111
2095
- /* Consume replies as long as there are more than zero */
2096
- if (c -> reply_len > 0 ) {
2097
- /* Push serialization settings from the cluster into our socket */
2098
- c -> cmd_sock -> serializer = c -> flags -> serializer ;
2112
+ if (c -> reply_len > 0 ) {
2113
+ /* Push serialization settings from the cluster into our socket */
2114
+ c -> cmd_sock -> serializer = c -> flags -> serializer ;
2099
2115
2100
- /* Call our specified callback */
2101
- if (cb (c -> cmd_sock , & z_result , c -> reply_len , ctx ) == FAILURE ) {
2102
- zval_dtor (& z_result );
2103
- CLUSTER_RETURN_FALSE (c );
2116
+ /* Call our specified callback */
2117
+ if (cb (c -> cmd_sock , & z_result , c -> reply_len , ctx ) == FAILURE ) {
2118
+ zval_dtor (& z_result );
2119
+ CLUSTER_RETURN_FALSE (c );
2120
+ }
2104
2121
}
2105
2122
}
2106
2123
@@ -2245,14 +2262,17 @@ PHP_REDIS_API void
2245
2262
cluster_xread_resp (INTERNAL_FUNCTION_PARAMETERS , redisCluster * c , void * ctx ) {
2246
2263
zval z_streams ;
2247
2264
2248
- array_init (& z_streams );
2249
-
2250
2265
c -> cmd_sock -> serializer = c -> flags -> serializer ;
2251
2266
c -> cmd_sock -> compression = c -> flags -> compression ;
2252
2267
2253
- if (redis_read_stream_messages_multi (c -> cmd_sock , c -> reply_len , & z_streams ) < 0 ) {
2254
- zval_dtor (& z_streams );
2255
- CLUSTER_RETURN_FALSE (c );
2268
+ if (c -> reply_len == -1 && c -> flags -> null_mbulk_as_null ) {
2269
+ ZVAL_NULL (& z_streams );
2270
+ } else {
2271
+ array_init (& z_streams );
2272
+ if (redis_read_stream_messages_multi (c -> cmd_sock , c -> reply_len , & z_streams ) < 0 ) {
2273
+ zval_dtor (& z_streams );
2274
+ CLUSTER_RETURN_FALSE (c );
2275
+ }
2256
2276
}
2257
2277
2258
2278
if (CLUSTER_IS_ATOMIC (c )) {
0 commit comments