diff options
Diffstat (limited to '18dc2aacd6ab25c2aaf92a43d32d8eaf4235dcc0.patch')
-rw-r--r-- | 18dc2aacd6ab25c2aaf92a43d32d8eaf4235dcc0.patch | 175 |
1 files changed, 175 insertions, 0 deletions
diff --git a/18dc2aacd6ab25c2aaf92a43d32d8eaf4235dcc0.patch b/18dc2aacd6ab25c2aaf92a43d32d8eaf4235dcc0.patch new file mode 100644 index 0000000..724abde --- /dev/null +++ b/18dc2aacd6ab25c2aaf92a43d32d8eaf4235dcc0.patch @@ -0,0 +1,175 @@ +From 18dc2aacd6ab25c2aaf92a43d32d8eaf4235dcc0 Mon Sep 17 00:00:00 2001 +From: Michael Grunder <michael.grunder@gmail.com> +Date: Tue, 6 Nov 2018 08:46:02 -0800 +Subject: [PATCH] 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. +--- + common.h | 2 ++ + library.c | 16 +++++++++---- + library.h | 1 + + redis_commands.c | 59 ++++++++++++++++++++++++++++++++++++++++-------- + 4 files changed, 63 insertions(+), 15 deletions(-) + +diff --git a/common.h b/common.h +index 0771cfd7..adbe3035 100644 +--- a/common.h ++++ b/common.h +@@ -461,8 +461,10 @@ typedef size_t strlen_t; + + #ifdef PHP_WIN32 + #define PHP_REDIS_API __declspec(dllexport) ++#define phpredis_atoi64(p) _atoi64((p)) + #else + #define PHP_REDIS_API ++#define phpredis_atoi64(p) atoll((p)) + #endif + + /* reply types */ +diff --git a/library.c b/library.c +index a6c93f9d..00d2f7ab 100644 +--- a/library.c ++++ b/library.c +@@ -698,6 +698,15 @@ int redis_cmd_append_sstr_long(smart_string *str, long append) { + return redis_cmd_append_sstr(str, long_buf, long_len); + } + ++/* ++ * Append a 64-bit integer to our command ++ */ ++int redis_cmd_append_sstr_i64(smart_string *str, int64_t append) { ++ char nbuf[64]; ++ int len = snprintf(nbuf, sizeof(nbuf), "%lld", append); ++ return redis_cmd_append_sstr(str, nbuf, len); ++} ++ + /* + * Append a double to a smart string command + */ +@@ -1080,11 +1089,8 @@ PHP_REDIS_API void redis_long_response(INTERNAL_FUNCTION_PARAMETERS, + } + + if(response[0] == ':') { +-#ifdef PHP_WIN32 +- __int64 ret = _atoi64(response + 1); +-#else +- long long ret = atoll(response + 1); +-#endif ++ int64_t ret = phpredis_atoi64(response + 1); ++ + if (IS_ATOMIC(redis_sock)) { + if(ret > LONG_MAX) { /* overflow */ + RETVAL_STRINGL(response + 1, response_len - 1); +diff --git a/library.h b/library.h +index 1c936dd5..80b12d03 100644 +--- a/library.h ++++ b/library.h +@@ -18,6 +18,7 @@ int redis_cmd_init_sstr(smart_string *str, int num_args, char *keyword, int keyw + int redis_cmd_append_sstr(smart_string *str, char *append, int append_len); + int redis_cmd_append_sstr_int(smart_string *str, int append); + int redis_cmd_append_sstr_long(smart_string *str, long append); ++int redis_cmd_append_sstr_i64(smart_string *str, int64_t append); + int redis_cmd_append_sstr_dbl(smart_string *str, double value); + int redis_cmd_append_sstr_zval(smart_string *str, zval *z, RedisSock *redis_sock TSRMLS_DC); + int redis_cmd_append_sstr_key(smart_string *str, char *key, strlen_t len, RedisSock *redis_sock, short *slot); +diff --git a/redis_commands.c b/redis_commands.c +index 14fb56f2..1ef216d4 100644 +--- a/redis_commands.c ++++ b/redis_commands.c +@@ -3525,13 +3525,56 @@ int redis_xack_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, + typedef struct xclaimOptions { + struct { + char *type; +- zend_long time; ++ int64_t time; + } idle; + zend_long retrycount; + int force; + int justid; + } xclaimOptions; + ++/* Attempt to extract an int64_t from the provided zval */ ++static int zval_get_i64(zval *zv, int64_t *retval) { ++ if (Z_TYPE_P(zv) == IS_LONG) { ++ *retval = (int64_t)Z_LVAL_P(zv); ++ return SUCCESS; ++ } else if (Z_TYPE_P(zv) == IS_DOUBLE) { ++ *retval = (int64_t)Z_DVAL_P(zv); ++ return SUCCESS; ++ } else if (Z_TYPE_P(zv) == IS_STRING) { ++ zend_long lval; ++ double dval; ++ ++ switch (is_numeric_string(Z_STRVAL_P(zv), Z_STRLEN_P(zv), &lval, &dval, 1)) { ++ case IS_LONG: ++ *retval = (int64_t)lval; ++ return SUCCESS; ++ case IS_DOUBLE: ++ *retval = (int64_t)dval; ++ return SUCCESS; ++ } ++ } ++ ++ /* If we make it here we have failed */ ++ return FAILURE; ++} ++ ++/* Helper function to get an integer XCLAIM argument. This can overflow a ++ * 32-bit PHP long so we have to extract it as an int64_t. If the value is ++ * not a valid number or negative, we'll inform the user of the problem and ++ * that the argument is being ignored. */ ++static int64_t get_xclaim_i64_arg(const char *key, zval *zv TSRMLS_DC) { ++ int64_t retval = -1; ++ ++ /* Extract an i64, and if we can't let the user know there is an issue. */ ++ if (zval_get_i64(zv, &retval) == FAILURE || retval < 0) { ++ php_error_docref(NULL TSRMLS_CC, E_WARNING, ++ "Invalid XCLAIM option '%s' will be ignored", key); ++ } ++ ++ /* Success */ ++ return retval; ++} ++ + /* Helper to extract XCLAIM options */ + static void get_xclaim_options(zval *z_arr, xclaimOptions *opt TSRMLS_DC) { + HashTable *ht; +@@ -3556,23 +3599,19 @@ static void get_xclaim_options(zval *z_arr, xclaimOptions *opt TSRMLS_DC) { + ht = Z_ARRVAL_P(z_arr); + ZEND_HASH_FOREACH_KEY_VAL(ht, idx, zkey, zv) { + if (zkey) { +- /* Every key => value xclaim option requires a long and Redis +- * treats -1 as not being passed so skip negative values too. */ +- if (Z_TYPE_P(zv) != IS_LONG || Z_LVAL_P(zv) < 0) +- continue; +- + kval = ZSTR_VAL(zkey); + klen = ZSTR_LEN(zkey); ++ + if (klen == 4) { + if (!strncasecmp(kval, "TIME", 4)) { + opt->idle.type = "TIME"; +- opt->idle.time = Z_LVAL_P(zv); ++ opt->idle.time = get_xclaim_i64_arg("TIME", zv TSRMLS_CC); + } else if (!strncasecmp(kval, "IDLE", 4)) { + opt->idle.type = "IDLE"; +- opt->idle.time = Z_LVAL_P(zv); ++ opt->idle.time = get_xclaim_i64_arg("IDLE", zv TSRMLS_CC); + } + } else if (klen == 10 && !strncasecmp(kval, "RETRYCOUNT", 10)) { +- opt->retrycount = Z_LVAL_P(zv); ++ opt->retrycount = zval_get_long(zv); + } + } else { + if (Z_TYPE_P(zv) == IS_STRING) { +@@ -3609,7 +3648,7 @@ static void append_xclaim_options(smart_string *cmd, xclaimOptions *opt) { + /* IDLE/TIME long */ + if (opt->idle.type != NULL && opt->idle.time != -1) { + redis_cmd_append_sstr(cmd, opt->idle.type, strlen(opt->idle.type)); +- redis_cmd_append_sstr_long(cmd, opt->idle.time); ++ redis_cmd_append_sstr_i64(cmd, opt->idle.time); + } + + /* RETRYCOUNT */ |