fix: reject zset variadic commands with 0 keys (#2022)

Fixes the assertion failure as reported by #1994.

Signed-off-by: Roman Gershman <roman@dragonflydb.io>
This commit is contained in:
Roman Gershman 2023-10-15 14:34:04 +03:00 committed by GitHub
parent 826b1d81a3
commit bcfd1863c7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 16 additions and 11 deletions

View file

@ -28,6 +28,8 @@ std::string_view StatusToMsg(OpStatus status) {
return "-BUSYGROUP Consumer Group name already exists";
case OpStatus::INVALID_NUMERIC_RESULT:
return kInvalidNumericResult;
case OpStatus::AT_LEAST_ONE_KEY:
return "at least 1 input key is needed for this command";
default:
LOG(ERROR) << "Unsupported status " << status;
return "Internal error";

View file

@ -27,6 +27,7 @@ enum class OpStatus : uint16_t {
ENTRIES_ADDED_SMALL,
INVALID_NUMERIC_RESULT,
CANCELLED,
AT_LEAST_ONE_KEY,
};
class OpResultBase {

View file

@ -1462,12 +1462,10 @@ OpResult<KeyIndex> DetermineKeys(const CommandId* cid, CmdArgList args) {
if (!absl::SimpleAtoi(num, &num_custom_keys) || num_custom_keys < 0)
return OpStatus::INVALID_INT;
if (name == "ZDIFF" && num_custom_keys == 0) {
return OpStatus::INVALID_INT;
}
if (name == "ZUNION" && num_custom_keys == 0) {
return OpStatus::SYNTAX_ERR;
if (num_custom_keys == 0 &&
(absl::StartsWith(name, "ZDIFF") || absl::StartsWith(name, "ZUNION") ||
absl::StartsWith(name, "ZINTER"))) {
return OpStatus::AT_LEAST_ONE_KEY;
}
if (args.size() < size_t(num_custom_keys) + num_keys_index + 1)

View file

@ -322,7 +322,7 @@ TEST_F(ZSetFamilyTest, ZUnionError) {
EXPECT_THAT(resp, ErrArg("wrong number of arguments"));
resp = Run({"zunion", "0", "myset"});
EXPECT_THAT(resp, ErrArg("syntax error"));
EXPECT_THAT(resp, ErrArg("at least 1 input key is needed"));
resp = Run({"zunion", "3", "z1", "z2", "z3", "weights", "1", "1", "k"});
EXPECT_THAT(resp, ErrArg("weight value is not a float"));
@ -402,7 +402,7 @@ TEST_F(ZSetFamilyTest, ZUnionStore) {
EXPECT_THAT(resp, ErrArg("wrong number of arguments"));
resp = Run({"zunionstore", "key", "0", "aggregate"});
EXPECT_THAT(resp, ErrArg("syntax error"));
EXPECT_THAT(resp, ErrArg("at least 1 input key is needed"));
resp = Run({"zunionstore", "key", "0", "aggregate", "sum"});
EXPECT_THAT(resp, ErrArg("at least 1 input key is needed"));
@ -476,11 +476,12 @@ TEST_F(ZSetFamilyTest, ZInterStore) {
TEST_F(ZSetFamilyTest, ZInterCard) {
EXPECT_EQ(3, CheckedInt({"zadd", "z1", "1", "a", "2", "b", "3", "c"}));
EXPECT_EQ(3, CheckedInt({"zadd", "z2", "2", "b", "3", "c", "4", "d"}));
RespExpr resp;
EXPECT_EQ(2, CheckedInt({"zintercard", "2", "z1", "z2"}));
EXPECT_EQ(1, CheckedInt({"zintercard", "2", "z1", "z2", "LIMIT", "1"}));
RespExpr resp;
resp = Run({"zintercard", "2", "z1", "z2", "LIM"});
EXPECT_THAT(resp, ErrArg("syntax error"));
resp = Run({"zintercard", "2", "z1", "z2", "LIMIT"});
@ -488,6 +489,9 @@ TEST_F(ZSetFamilyTest, ZInterCard) {
resp = Run({"zintercard", "2", "z1", "z2", "LIMIT", "a"});
EXPECT_THAT(resp, ErrArg("limit value is not a positive integer"));
resp = Run({"zintercard", "0", "z1"});
EXPECT_THAT(resp, ErrArg("at least 1 input"));
// support for sets
EXPECT_EQ(3, CheckedInt({"sadd", "s2", "b", "c", "d"}));
EXPECT_EQ(2, CheckedInt({"zintercard", "2", "z1", "s2"}));
@ -632,10 +636,10 @@ TEST_F(ZSetFamilyTest, ZDiffError) {
EXPECT_THAT(resp, ErrArg("wrong number of arguments"));
resp = Run({"zdiff", "0", "z1"});
EXPECT_THAT(resp, ErrArg("value is not an integer or out of range"));
EXPECT_THAT(resp, ErrArg("at least 1 input key is needed"));
resp = Run({"zdiff", "0", "z1", "z2"});
EXPECT_THAT(resp, ErrArg("value is not an integer or out of range"));
EXPECT_THAT(resp, ErrArg("at least 1 input key is needed"));
}
TEST_F(ZSetFamilyTest, ZDiff) {