Skip to content

Commit

Permalink
EVALSHA_RO and EVAL_RO Commands (redis#8820)
Browse files Browse the repository at this point in the history
* EVALSHA_RO and EVAL_RO Commands

Added new readonly versions of EVAL
and EVALSHA.
  • Loading branch information
nmvk authored May 13, 2021
1 parent e01c92a commit 31edc22
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 0 deletions.
17 changes: 17 additions & 0 deletions src/scripting.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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
Expand All @@ -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[] = {
Expand Down
8 changes: 8 additions & 0 deletions src/server.c
Original file line number Diff line number Diff line change
Expand Up @@ -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},
Expand Down
2 changes: 2 additions & 0 deletions src/server.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
11 changes: 11 additions & 0 deletions tests/unit/scripting.tcl
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down

0 comments on commit 31edc22

Please sign in to comment.