Skip to content

Commit 67c36b7

Browse files
More substanitive path diversion for php5 and php7
The php cyclical garbage collection mechanism in php 5.x transparently wraps additional information around ARRAY and OBJECT zval variables meaning we cannot point to stack allocated zval structs under certain conditions.
1 parent ff8569b commit 67c36b7

File tree

1 file changed

+54
-6
lines changed

1 file changed

+54
-6
lines changed

redis_array_impl.c

Lines changed: 54 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include "SAPI.h"
2525
#include "ext/standard/url.h"
2626
#include "ext/standard/crc32.h"
27+
#include "zend_interfaces.h"
2728

2829
#define PHPREDIS_INDEX_NAME "__phpredis_array_index__"
2930

@@ -970,6 +971,40 @@ ra_move_string(const char *key, int key_len, zval *z_from, zval *z_to, long ttl
970971
return 1;
971972
}
972973

974+
#if (PHP_MAJOR_VERSION < 7)
975+
976+
static zend_bool
977+
ra_move_hash(const char *key, int key_len, zval *z_from, zval *z_to, long ttl TSRMLS_DC) {
978+
zval *z_ret, *z_arg1;
979+
980+
/* Call HMGET on the source host */
981+
MAKE_STD_ZVAL(z_arg1);
982+
ZVAL_STRINGL(z_arg1, key, key_len);
983+
zend_call_method_with_1_params(&z_from, redis_ce, NULL, "hgetall", &z_ret, z_arg1);
984+
985+
/* Abort if we don't get a proper response */
986+
if (!z_ret || Z_TYPE_P(z_ret) != IS_ARRAY) {
987+
if (z_ret) zval_ptr_dtor(&z_ret);
988+
zval_ptr_dtor(&z_arg1);
989+
return 0;
990+
}
991+
992+
/* Now run HMSET on destination host with the results of our HGETALL call */
993+
zend_call_method_with_2_params(&z_to, redis_ce, NULL, "hmset", NULL, z_arg1, z_ret);
994+
995+
/* Expire key if needed */
996+
ra_expire_key(key, key_len, z_to, ttl TSRMLS_CC);
997+
998+
/* cleanup */
999+
zval_ptr_dtor(&z_ret);
1000+
zval_ptr_dtor(&z_arg1);
1001+
zval_ptr_dtor(&z_ret);
1002+
1003+
return 1;
1004+
}
1005+
1006+
#else
1007+
9731008
static zend_bool
9741009
ra_move_hash(const char *key, int key_len, zval *z_from, zval *z_to, long ttl TSRMLS_DC) {
9751010
zval z_fun_hgetall, z_fun_hmset, z_ret_dest, z_args[2];
@@ -1003,6 +1038,8 @@ ra_move_hash(const char *key, int key_len, zval *z_from, zval *z_to, long ttl TS
10031038
return 1;
10041039
}
10051040

1041+
#endif
1042+
10061043
static zend_bool
10071044
ra_move_collection(const char *key, int key_len, zval *z_from, zval *z_to,
10081045
int list_count, const char **cmd_list, int add_count,
@@ -1139,30 +1176,41 @@ ra_move_key(const char *key, int key_len, zval *z_from, zval *z_to TSRMLS_DC)
11391176
static void zval_rehash_callback(zend_fcall_info *z_cb, zend_fcall_info_cache *z_cb_cache,
11401177
const char *hostname, long count, zval *z_ret TSRMLS_DC)
11411178
{
1179+
#if (PHP_MAJOR_VERSION < 7)
1180+
zval *z_args[2];
11421181

1143-
zval z_args[2];
1182+
MAKE_STD_ZVAL(z_args[0]);
1183+
MAKE_STD_ZVAL(z_args[1]);
1184+
ZVAL_STRINGL(z_args[0], hostname, 0);
1185+
ZVAL_LONG(z_args[1], count);
11441186

1145-
ZVAL_STRING(&z_args[0], hostname);
1146-
ZVAL_LONG(&z_args[1], count);
1187+
zval **z_args_pp[2] = { &z_args[0], &z_args[1] };
11471188

1148-
#if (PHP_MAJOR_VERSION < 7)
1149-
zval *z_host = &z_args[0], *z_count = &z_args[1], **z_args_pp[2] = { &z_host, &z_count };
11501189
z_cb->params = z_args_pp;
11511190
z_cb->retval_ptr_ptr = &z_ret;
11521191
#else
1192+
zval z_args[2];
1193+
1194+
ZVAL_STRING(&z_args[0], hostname);
1195+
ZVAL_LONG(&z_args[1], count);
1196+
11531197
z_cb->params = z_args;
11541198
z_cb->retval = z_ret;
11551199
#endif
1200+
11561201
z_cb->param_count = 2;
11571202
z_cb->no_separation = 0;
11581203

11591204
/* run cb(hostname, count) */
11601205
zend_call_function(z_cb, z_cb_cache TSRMLS_CC);
11611206

11621207
/* cleanup */
1163-
zval_dtor(&z_args[0]);
11641208
#if (PHP_MAJOR_VERSION < 7)
1209+
zval_ptr_dtor(&z_args[0]);
1210+
zval_ptr_dtor(&z_args[1]);
11651211
zval_ptr_dtor(&z_ret);
1212+
#else
1213+
zval_dtor(&z_args[0]);
11661214
#endif
11671215
}
11681216

0 commit comments

Comments
 (0)