diff --git a/src/db.c b/src/db.c index 79d754d3b..48462ddb0 100644 --- a/src/db.c +++ b/src/db.c @@ -1871,8 +1871,9 @@ int64_t getAllKeySpecsFlags(struct redisCommand *cmd, int inv) { * found in other valid keyspecs. */ int getKeysUsingKeySpecs(struct redisCommand *cmd, robj **argv, int argc, int search_flags, getKeysResult *result) { - int j, i, k = 0, last, first, step; + int j, i, last, first, step; keyReference *keys; + result->numkeys = 0; for (j = 0; j < cmd->key_specs_num; j++) { keySpec *spec = cmd->key_specs + j; @@ -1937,7 +1938,7 @@ int getKeysUsingKeySpecs(struct redisCommand *cmd, robj **argv, int argc, int se } int count = ((last - first)+1); - keys = getKeysPrepareResult(result, count); + keys = getKeysPrepareResult(result, result->numkeys + count); /* First or last is out of bounds, which indicates a syntax error */ if (last >= argc || last < first || first >= argc) { @@ -1958,8 +1959,9 @@ int getKeysUsingKeySpecs(struct redisCommand *cmd, robj **argv, int argc, int se serverPanic("Redis built-in command declared keys positions not matching the arity requirements."); } } - keys[k].pos = i; - keys[k++].flags = spec->flags; + keys[result->numkeys].pos = i; + keys[result->numkeys].flags = spec->flags; + result->numkeys++; } /* Handle incomplete specs (only after we added the current spec @@ -1980,8 +1982,7 @@ invalid_spec: } } - result->numkeys = k; - return k; + return result->numkeys; } /* Return all the arguments that are keys in the command passed via argc / argv. diff --git a/tests/unit/introspection-2.tcl b/tests/unit/introspection-2.tcl index 52a13edf7..89cb4b122 100644 --- a/tests/unit/introspection-2.tcl +++ b/tests/unit/introspection-2.tcl @@ -153,6 +153,21 @@ start_server {tags {"introspection"}} { assert_equal {key1 key2} [r command getkeys lcs key1 key2] } + test {COMMAND GETKEYS MORE THAN 256 KEYS} { + set all_keys [list] + set numkeys 260 + for {set i 1} {$i <= $numkeys} {incr i} { + lappend all_keys "key$i" + } + set all_keys_with_target [linsert $all_keys 0 target] + # we are using ZUNIONSTORE command since in order to reproduce allocation of a new buffer in getKeysPrepareResult + # when numkeys in result > 0 + # we need a command that the final number of keys is not known in the first call to getKeysPrepareResult + # before the fix in that case data of old buffer was not copied to the new result buffer + # causing all previous keys (numkeys) data to be uninitialize + assert_equal $all_keys_with_target [r command getkeys ZUNIONSTORE target $numkeys {*}$all_keys] + } + test "COMMAND LIST syntax error" { assert_error "ERR syntax error*" {r command list bad_arg} assert_error "ERR syntax error*" {r command list filterby bad_arg}