Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/phpredis/phpredis.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Grunder <michael.grunder@gmail.com>2020-08-30 23:51:12 +0300
committerGitHub <noreply@github.com>2020-08-30 23:51:12 +0300
commit364580718891de94aac13dc352aa994d531d4272 (patch)
tree3888c16423d5c9110a8efb7b6181a4d772822198 /redis_commands.c
parent2351d12491621e0b024db95722108b229cb8bec3 (diff)
Relax requirements on set's expire argument (#1830)
Relax requirements on set's expire argument See: #1783
Diffstat (limited to 'redis_commands.c')
-rw-r--r--redis_commands.c49
1 files changed, 37 insertions, 12 deletions
diff --git a/redis_commands.c b/redis_commands.c
index 9601b395..d6bb2bcf 100644
--- a/redis_commands.c
+++ b/redis_commands.c
@@ -1299,6 +1299,34 @@ int redis_blocking_pop_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
* have specific processing (argument validation, etc) that make them unique
*/
+/* Attempt to pull a long expiry from a zval. We're more restrictave than zval_get_long
+ * because that function will return integers from things like open file descriptors
+ * which should simply fail as a TTL */
+static int redis_try_get_expiry(zval *zv, zend_long *lval) {
+ double dval;
+
+ /* Success on an actual long or double */
+ if (Z_TYPE_P(zv) == IS_LONG || Z_TYPE_P(zv) == IS_DOUBLE) {
+ *lval = zval_get_long(zv);
+ return SUCCESS;
+ }
+
+ /* Automatically fail if we're not a string */
+ if (Z_TYPE_P(zv) != IS_STRING)
+ return FAILURE;
+
+ /* Attempt to get a long from the string */
+ switch (is_numeric_string(Z_STRVAL_P(zv), Z_STRLEN_P(zv), lval, &dval, 0)) {
+ case IS_DOUBLE:
+ *lval = dval;
+ /* fallthrough */
+ case IS_LONG:
+ return SUCCESS;
+ default:
+ return FAILURE;
+ }
+}
+
/* SET */
int redis_set_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
char **cmd, int *cmd_len, short *slot, void **ctx)
@@ -1306,7 +1334,8 @@ int redis_set_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
smart_string cmdstr = {0};
zval *z_value, *z_opts=NULL;
char *key = NULL, *exp_type = NULL, *set_type = NULL;
- long expire = -1, exp_set = 0, keep_ttl = 0;
+ long exp_set = 0, keep_ttl = 0;
+ zend_long expire = -1;
size_t key_len;
// Make sure the function is being called correctly
@@ -1316,14 +1345,6 @@ int redis_set_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
return FAILURE;
}
- /* Our optional argument can either be a long (to support legacy SETEX */
- /* redirection), or an array with Redis >= 2.6.12 set options */
- if (z_opts && Z_TYPE_P(z_opts) != IS_LONG && Z_TYPE_P(z_opts) != IS_ARRAY
- && Z_TYPE_P(z_opts) != IS_NULL)
- {
- return FAILURE;
- }
-
// Check for an options array
if (z_opts && Z_TYPE_P(z_opts) == IS_ARRAY) {
HashTable *kt = Z_ARRVAL_P(z_opts);
@@ -1355,8 +1376,12 @@ int redis_set_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
set_type = Z_STRVAL_P(v);
}
} ZEND_HASH_FOREACH_END();
- } else if (z_opts && Z_TYPE_P(z_opts) == IS_LONG) {
- expire = Z_LVAL_P(z_opts);
+ } else if (z_opts && Z_TYPE_P(z_opts) != IS_NULL) {
+ if (redis_try_get_expiry(z_opts, &expire) == FAILURE) {
+ php_error_docref(NULL, E_WARNING, "Expire must be a long, double, or a numeric string");
+ return FAILURE;
+ }
+
exp_set = 1;
}
@@ -1386,7 +1411,7 @@ int redis_set_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
if (exp_type) {
redis_cmd_append_sstr(&cmdstr, exp_type, strlen(exp_type));
- redis_cmd_append_sstr_long(&cmdstr, expire);
+ redis_cmd_append_sstr_long(&cmdstr, (long)expire);
}
if (set_type)