summaryrefslogtreecommitdiffstats
path: root/18dc2aacd6ab25c2aaf92a43d32d8eaf4235dcc0.patch
diff options
context:
space:
mode:
Diffstat (limited to '18dc2aacd6ab25c2aaf92a43d32d8eaf4235dcc0.patch')
-rw-r--r--18dc2aacd6ab25c2aaf92a43d32d8eaf4235dcc0.patch175
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 */