diff --git a/src/db.c b/src/db.c index 99212bac4..36de2aa0a 100644 --- a/src/db.c +++ b/src/db.c @@ -2389,6 +2389,7 @@ int setGetKeys(struct redisCommand *cmd, robj **argv, int argc, getKeysResult *r * read-only if the BITFIELD GET subcommand is used. */ int bitfieldGetKeys(struct redisCommand *cmd, robj **argv, int argc, getKeysResult *result) { keyReference *keys; + int readonly = 1; UNUSED(cmd); keys = getKeysPrepareResult(result, 1); @@ -2399,11 +2400,23 @@ int bitfieldGetKeys(struct redisCommand *cmd, robj **argv, int argc, getKeysResu int remargs = argc - i - 1; /* Remaining args other than current. */ char *arg = argv[i]->ptr; if (!strcasecmp(arg, "get") && remargs >= 2) { - keys[0].flags = CMD_KEY_RO | CMD_KEY_ACCESS; - return 1; + i += 2; + } else if ((!strcasecmp(arg, "set") || !strcasecmp(arg, "incrby")) && remargs >= 3) { + readonly = 0; + i += 3; + break; + } else if (!strcasecmp(arg, "overflow") && remargs >= 1) { + i += 1; + } else { + readonly = 0; /* Syntax error. safer to assume non-RO. */ + break; } } - keys[0].flags = CMD_KEY_RW | CMD_KEY_ACCESS | CMD_KEY_UPDATE; + if (readonly) { + keys[0].flags = CMD_KEY_RO | CMD_KEY_ACCESS; + } else { + keys[0].flags = CMD_KEY_RW | CMD_KEY_ACCESS | CMD_KEY_UPDATE; + } return 1; } diff --git a/tests/unit/acl-v2.tcl b/tests/unit/acl-v2.tcl index 500a7c729..451b5883e 100644 --- a/tests/unit/acl-v2.tcl +++ b/tests/unit/acl-v2.tcl @@ -195,6 +195,7 @@ start_server {tags {"acl external:skip"}} { # We don't have the permission to WRITE key. assert_error {*NOPERM*keys*} {$r2 bitfield readstr set u4 0 1} + assert_error {*NOPERM*keys*} {$r2 bitfield readstr get u4 0 set u4 0 1} assert_error {*NOPERM*keys*} {$r2 bitfield readstr incrby u4 0 1} }