Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 18dc2aa

Browse files
32bit xclaim fix (#1444)
This should fix the XCLAIM issue on 32-bit PHP installs. This change will allow the user to pass the XCLAIM TIME option pretty much any way they want (string, long, or float) and it should work. Note that in 32-bit PHP they will only be able to pass exact values <= 2^53 as PHP will use a double precision floating point for integer overflows.
1 parent b509391 commit 18dc2aa

4 files changed

Lines changed: 63 additions & 15 deletions

File tree

common.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -461,8 +461,10 @@ typedef size_t strlen_t;
461461

462462
#ifdef PHP_WIN32
463463
#define PHP_REDIS_API __declspec(dllexport)
464+
#define phpredis_atoi64(p) _atoi64((p))
464465
#else
465466
#define PHP_REDIS_API
467+
#define phpredis_atoi64(p) atoll((p))
466468
#endif
467469

468470
/* reply types */

library.c

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -698,6 +698,15 @@ int redis_cmd_append_sstr_long(smart_string *str, long append) {
698698
return redis_cmd_append_sstr(str, long_buf, long_len);
699699
}
700700

701+
/*
702+
* Append a 64-bit integer to our command
703+
*/
704+
int redis_cmd_append_sstr_i64(smart_string *str, int64_t append) {
705+
char nbuf[64];
706+
int len = snprintf(nbuf, sizeof(nbuf), "%lld", append);
707+
return redis_cmd_append_sstr(str, nbuf, len);
708+
}
709+
701710
/*
702711
* Append a double to a smart string command
703712
*/
@@ -1080,11 +1089,8 @@ PHP_REDIS_API void redis_long_response(INTERNAL_FUNCTION_PARAMETERS,
10801089
}
10811090

10821091
if(response[0] == ':') {
1083-
#ifdef PHP_WIN32
1084-
__int64 ret = _atoi64(response + 1);
1085-
#else
1086-
long long ret = atoll(response + 1);
1087-
#endif
1092+
int64_t ret = phpredis_atoi64(response + 1);
1093+
10881094
if (IS_ATOMIC(redis_sock)) {
10891095
if(ret > LONG_MAX) { /* overflow */
10901096
RETVAL_STRINGL(response + 1, response_len - 1);

library.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ int redis_cmd_init_sstr(smart_string *str, int num_args, char *keyword, int keyw
1818
int redis_cmd_append_sstr(smart_string *str, char *append, int append_len);
1919
int redis_cmd_append_sstr_int(smart_string *str, int append);
2020
int redis_cmd_append_sstr_long(smart_string *str, long append);
21+
int redis_cmd_append_sstr_i64(smart_string *str, int64_t append);
2122
int redis_cmd_append_sstr_dbl(smart_string *str, double value);
2223
int redis_cmd_append_sstr_zval(smart_string *str, zval *z, RedisSock *redis_sock TSRMLS_DC);
2324
int redis_cmd_append_sstr_key(smart_string *str, char *key, strlen_t len, RedisSock *redis_sock, short *slot);

redis_commands.c

Lines changed: 49 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3525,13 +3525,56 @@ int redis_xack_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
35253525
typedef struct xclaimOptions {
35263526
struct {
35273527
char *type;
3528-
zend_long time;
3528+
int64_t time;
35293529
} idle;
35303530
zend_long retrycount;
35313531
int force;
35323532
int justid;
35333533
} xclaimOptions;
35343534

3535+
/* Attempt to extract an int64_t from the provided zval */
3536+
static int zval_get_i64(zval *zv, int64_t *retval) {
3537+
if (Z_TYPE_P(zv) == IS_LONG) {
3538+
*retval = (int64_t)Z_LVAL_P(zv);
3539+
return SUCCESS;
3540+
} else if (Z_TYPE_P(zv) == IS_DOUBLE) {
3541+
*retval = (int64_t)Z_DVAL_P(zv);
3542+
return SUCCESS;
3543+
} else if (Z_TYPE_P(zv) == IS_STRING) {
3544+
zend_long lval;
3545+
double dval;
3546+
3547+
switch (is_numeric_string(Z_STRVAL_P(zv), Z_STRLEN_P(zv), &lval, &dval, 1)) {
3548+
case IS_LONG:
3549+
*retval = (int64_t)lval;
3550+
return SUCCESS;
3551+
case IS_DOUBLE:
3552+
*retval = (int64_t)dval;
3553+
return SUCCESS;
3554+
}
3555+
}
3556+
3557+
/* If we make it here we have failed */
3558+
return FAILURE;
3559+
}
3560+
3561+
/* Helper function to get an integer XCLAIM argument. This can overflow a
3562+
* 32-bit PHP long so we have to extract it as an int64_t. If the value is
3563+
* not a valid number or negative, we'll inform the user of the problem and
3564+
* that the argument is being ignored. */
3565+
static int64_t get_xclaim_i64_arg(const char *key, zval *zv TSRMLS_DC) {
3566+
int64_t retval = -1;
3567+
3568+
/* Extract an i64, and if we can't let the user know there is an issue. */
3569+
if (zval_get_i64(zv, &retval) == FAILURE || retval < 0) {
3570+
php_error_docref(NULL TSRMLS_CC, E_WARNING,
3571+
"Invalid XCLAIM option '%s' will be ignored", key);
3572+
}
3573+
3574+
/* Success */
3575+
return retval;
3576+
}
3577+
35353578
/* Helper to extract XCLAIM options */
35363579
static void get_xclaim_options(zval *z_arr, xclaimOptions *opt TSRMLS_DC) {
35373580
HashTable *ht;
@@ -3556,23 +3599,19 @@ static void get_xclaim_options(zval *z_arr, xclaimOptions *opt TSRMLS_DC) {
35563599
ht = Z_ARRVAL_P(z_arr);
35573600
ZEND_HASH_FOREACH_KEY_VAL(ht, idx, zkey, zv) {
35583601
if (zkey) {
3559-
/* Every key => value xclaim option requires a long and Redis
3560-
* treats -1 as not being passed so skip negative values too. */
3561-
if (Z_TYPE_P(zv) != IS_LONG || Z_LVAL_P(zv) < 0)
3562-
continue;
3563-
35643602
kval = ZSTR_VAL(zkey);
35653603
klen = ZSTR_LEN(zkey);
3604+
35663605
if (klen == 4) {
35673606
if (!strncasecmp(kval, "TIME", 4)) {
35683607
opt->idle.type = "TIME";
3569-
opt->idle.time = Z_LVAL_P(zv);
3608+
opt->idle.time = get_xclaim_i64_arg("TIME", zv TSRMLS_CC);
35703609
} else if (!strncasecmp(kval, "IDLE", 4)) {
35713610
opt->idle.type = "IDLE";
3572-
opt->idle.time = Z_LVAL_P(zv);
3611+
opt->idle.time = get_xclaim_i64_arg("IDLE", zv TSRMLS_CC);
35733612
}
35743613
} else if (klen == 10 && !strncasecmp(kval, "RETRYCOUNT", 10)) {
3575-
opt->retrycount = Z_LVAL_P(zv);
3614+
opt->retrycount = zval_get_long(zv);
35763615
}
35773616
} else {
35783617
if (Z_TYPE_P(zv) == IS_STRING) {
@@ -3609,7 +3648,7 @@ static void append_xclaim_options(smart_string *cmd, xclaimOptions *opt) {
36093648
/* IDLE/TIME long */
36103649
if (opt->idle.type != NULL && opt->idle.time != -1) {
36113650
redis_cmd_append_sstr(cmd, opt->idle.type, strlen(opt->idle.type));
3612-
redis_cmd_append_sstr_long(cmd, opt->idle.time);
3651+
redis_cmd_append_sstr_i64(cmd, opt->idle.time);
36133652
}
36143653

36153654
/* RETRYCOUNT */

0 commit comments

Comments
 (0)