summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRaghav Muddur <r@nmvk.com>2021-05-12 21:07:34 -0700
committerGitHub <noreply@github.com>2021-05-12 21:07:34 -0700
commit31edc22ecc6f21ab53dd6254b135fbfd5be23e2c (patch)
tree47862126e19890bfb8837fc862434cec19d68e4a
parente01c92a5ef6127067922f74cd8dac2ba72a1ad52 (diff)
downloadredis-31edc22ecc6f21ab53dd6254b135fbfd5be23e2c.tar.gz
EVALSHA_RO and EVAL_RO Commands (#8820)
* EVALSHA_RO and EVAL_RO Commands Added new readonly versions of EVAL and EVALSHA.
-rw-r--r--src/scripting.c17
-rw-r--r--src/server.c8
-rw-r--r--src/server.h2
-rw-r--r--tests/unit/scripting.tcl11
4 files changed, 38 insertions, 0 deletions
diff --git a/src/scripting.c b/src/scripting.c
index dbbd50eaf..a0f6c31f4 100644
--- a/src/scripting.c
+++ b/src/scripting.c
@@ -603,6 +603,15 @@ int luaRedisGenericCommand(lua_State *lua, int raise_error) {
goto cleanup;
}
+ /* This check is for EVAL_RO, EVALSHA_RO. We want to allow only read only commands */
+ if ((server.lua_caller->cmd->proc == evalRoCommand ||
+ server.lua_caller->cmd->proc == evalShaRoCommand) &&
+ (cmd->flags & CMD_WRITE))
+ {
+ luaPushError(lua, "Write commands are not allowed from read-only scripts");
+ goto cleanup;
+ }
+
/* Check the ACLs. */
int acl_errpos;
int acl_retval = ACLCheckAllPerm(c,&acl_errpos);
@@ -1696,6 +1705,10 @@ void evalCommand(client *c) {
evalGenericCommandWithDebugging(c,0);
}
+void evalRoCommand(client *c) {
+ evalCommand(c);
+}
+
void evalShaCommand(client *c) {
if (sdslen(c->argv[1]->ptr) != 40) {
/* We know that a match is not possible if the provided SHA is
@@ -1713,6 +1726,10 @@ void evalShaCommand(client *c) {
}
}
+void evalShaRoCommand(client *c) {
+ evalShaCommand(c);
+}
+
void scriptCommand(client *c) {
if (c->argc == 2 && !strcasecmp(c->argv[1]->ptr,"help")) {
const char *help[] = {
diff --git a/src/server.c b/src/server.c
index 95202f9fa..46151619d 100644
--- a/src/server.c
+++ b/src/server.c
@@ -910,10 +910,18 @@ struct redisCommand redisCommandTable[] = {
"no-script may-replicate @scripting",
0,evalGetKeys,0,0,0,0,0,0},
+ {"eval_ro",evalRoCommand,-3,
+ "no-script @scripting",
+ 0,evalGetKeys,0,0,0,0,0,0},
+
{"evalsha",evalShaCommand,-3,
"no-script may-replicate @scripting",
0,evalGetKeys,0,0,0,0,0,0},
+ {"evalsha_ro",evalShaRoCommand,-3,
+ "no-script @scripting",
+ 0,evalGetKeys,0,0,0,0,0,0},
+
{"slowlog",slowlogCommand,-2,
"admin random ok-loading ok-stale",
0,NULL,0,0,0,0,0,0},
diff --git a/src/server.h b/src/server.h
index 127f24929..146c57c19 100644
--- a/src/server.h
+++ b/src/server.h
@@ -2644,7 +2644,9 @@ void memoryCommand(client *c);
void clientCommand(client *c);
void helloCommand(client *c);
void evalCommand(client *c);
+void evalRoCommand(client *c);
void evalShaCommand(client *c);
+void evalShaRoCommand(client *c);
void scriptCommand(client *c);
void timeCommand(client *c);
void bitopCommand(client *c);
diff --git a/tests/unit/scripting.tcl b/tests/unit/scripting.tcl
index 0efe34cad..d5c876f3d 100644
--- a/tests/unit/scripting.tcl
+++ b/tests/unit/scripting.tcl
@@ -320,6 +320,17 @@ start_server {tags {"scripting"}} {
r eval {return 'hello' --trailing comment} 0
} {hello}
+ test {EVAL_RO - Successful case} {
+ r set foo bar
+ assert_equal bar [r eval_ro {return redis.call('get', KEYS[1]);} 1 foo]
+ }
+
+ test {EVAL_RO - Cannot run write commands} {
+ r set foo bar
+ catch {r eval_ro {redis.call('del', KEYS[1]);} 1 foo} e
+ set e
+ } {*Write commands are not allowed from read-only scripts*}
+
test {SCRIPTING FLUSH - is able to clear the scripts cache?} {
r set mykey myval
set v [r evalsha fd758d1589d044dd850a6f05d52f2eefd27f033f 1 mykey]