summaryrefslogtreecommitdiff
path: root/src/module.c
diff options
context:
space:
mode:
authorShaya Potter <shaya@redislabs.com>2022-08-28 13:10:10 +0300
committerGitHub <noreply@github.com>2022-08-28 13:10:10 +0300
commitbed6d759bcb1ddcdab76da1b46a120e2e610036b (patch)
tree9003af58459db53d8be6912bbb276c7ff5200413 /src/module.c
parent8945067544706951fd60007ad8cba8e8941b970d (diff)
downloadredis-bed6d759bcb1ddcdab76da1b46a120e2e610036b.tar.gz
Improve cmd_flags for script/functions in RM_Call (#11159)
When RM_Call was used with `M` (reject OOM), `W` (reject writes), as well as `S` (rejecting stale or write commands in "Script mode"), it would have only checked the command flags, but not the declared script flag in case it's a command that runs a script. Refactoring: extracts out similar code in server.c's processCommand to be usable in RM_Call as well.
Diffstat (limited to 'src/module.c')
-rw-r--r--src/module.c17
1 files changed, 10 insertions, 7 deletions
diff --git a/src/module.c b/src/module.c
index f0f49837b..776d74b65 100644
--- a/src/module.c
+++ b/src/module.c
@@ -592,6 +592,7 @@ void moduleReleaseTempClient(client *c) {
c->bufpos = 0;
c->flags = CLIENT_MODULE;
c->user = NULL; /* Root user */
+ c->cmd = c->lastcmd = c->realcmd = NULL;
moduleTempClients[moduleTempClientCount++] = c;
}
@@ -5781,7 +5782,6 @@ fmterr:
* This API is documented here: https://redis.io/topics/modules-intro
*/
RedisModuleCallReply *RM_Call(RedisModuleCtx *ctx, const char *cmdname, const char *fmt, ...) {
- struct redisCommand *cmd;
client *c = NULL;
robj **argv = NULL;
int argc = 0, argv_len = 0, flags = 0;
@@ -5789,6 +5789,7 @@ RedisModuleCallReply *RM_Call(RedisModuleCtx *ctx, const char *cmdname, const ch
RedisModuleCallReply *reply = NULL;
int replicate = 0; /* Replicate this command? */
int error_as_call_replies = 0; /* return errors as RedisModuleCallReply object */
+ uint64_t cmd_flags;
/* Handle arguments. */
va_start(ap, fmt);
@@ -5831,7 +5832,7 @@ RedisModuleCallReply *RM_Call(RedisModuleCtx *ctx, const char *cmdname, const ch
/* Lookup command now, after filters had a chance to make modifications
* if necessary.
*/
- cmd = c->cmd = c->lastcmd = c->realcmd = lookupCommand(c->argv,c->argc);
+ c->cmd = c->lastcmd = c->realcmd = lookupCommand(c->argv,c->argc);
sds err;
if (!commandCheckExistence(c, error_as_call_replies? &err : NULL)) {
errno = ENOENT;
@@ -5846,10 +5847,12 @@ RedisModuleCallReply *RM_Call(RedisModuleCtx *ctx, const char *cmdname, const ch
goto cleanup;
}
+ cmd_flags = getCommandFlags(c);
+
if (flags & REDISMODULE_ARGV_SCRIPT_MODE) {
/* Basically on script mode we want to only allow commands that can
* be executed on scripts (CMD_NOSCRIPT is not set on the command flags) */
- if (cmd->flags & CMD_NOSCRIPT) {
+ if (cmd_flags & CMD_NOSCRIPT) {
errno = ESPIPE;
if (error_as_call_replies) {
sds msg = sdscatfmt(sdsempty(), "command '%S' is not allowed on script mode", c->cmd->fullname);
@@ -5860,7 +5863,7 @@ RedisModuleCallReply *RM_Call(RedisModuleCtx *ctx, const char *cmdname, const ch
}
if (flags & REDISMODULE_ARGV_RESPECT_DENY_OOM) {
- if (cmd->flags & CMD_DENYOOM) {
+ if (cmd_flags & CMD_DENYOOM) {
int oom_state;
if (ctx->flags & REDISMODULE_CTX_THREAD_SAFE) {
/* On background thread we can not count on server.pre_command_oom_state.
@@ -5882,7 +5885,7 @@ RedisModuleCallReply *RM_Call(RedisModuleCtx *ctx, const char *cmdname, const ch
}
if (flags & REDISMODULE_ARGV_NO_WRITES) {
- if (cmd->flags & CMD_WRITE) {
+ if (cmd_flags & CMD_WRITE) {
errno = ENOSPC;
if (error_as_call_replies) {
sds msg = sdscatfmt(sdsempty(), "Write command '%S' was "
@@ -5895,7 +5898,7 @@ RedisModuleCallReply *RM_Call(RedisModuleCtx *ctx, const char *cmdname, const ch
/* Script mode tests */
if (flags & REDISMODULE_ARGV_SCRIPT_MODE) {
- if (cmd->flags & CMD_WRITE) {
+ if (cmd_flags & CMD_WRITE) {
/* on script mode, if a command is a write command,
* We will not run it if we encounter disk error
* or we do not have enough replicas */
@@ -5932,7 +5935,7 @@ RedisModuleCallReply *RM_Call(RedisModuleCtx *ctx, const char *cmdname, const ch
}
if (server.masterhost && server.repl_state != REPL_STATE_CONNECTED &&
- server.repl_serve_stale_data == 0 && !(cmd->flags & CMD_STALE)) {
+ server.repl_serve_stale_data == 0 && !(cmd_flags & CMD_STALE)) {
errno = ESPIPE;
if (error_as_call_replies) {
sds msg = sdsdup(shared.masterdownerr->ptr);