fix(lua): Avoid infinite loop and fix sha compatibility with redis.

Fixes #146 and fixes #147.

Signed-off-by: Roman Gershman <roman@dragonflydb.io>
This commit is contained in:
Roman Gershman 2022-06-13 23:32:19 +03:00
parent f24005407b
commit c23dc1c94c
4 changed files with 18 additions and 9 deletions

View File

@ -514,6 +514,7 @@ size_t DbSlice::DbSize(DbIndex db_ind) const {
bool DbSlice::Acquire(IntentLock::Mode mode, const KeyLockArgs& lock_args) {
DCHECK(!lock_args.args.empty());
DCHECK_GT(lock_args.key_step, 0u);
auto& lt = db_arr_[lock_args.db_index]->trans_locks;
bool lock_acquired = true;

View File

@ -283,6 +283,9 @@ TEST_F(DflyEngineTest, Eval) {
ASSERT_FALSE(service_->IsLocked(0, "foo"));
ASSERT_FALSE(service_->IsShardSetLocked());
resp = Run({"eval", "return 77", "2", "foo", "zoo"});
EXPECT_THAT(resp, IntArg(77));
}
TEST_F(DflyEngineTest, EvalResp) {
@ -322,15 +325,18 @@ TEST_F(DflyEngineTest, EvalSha) {
resp = Run({"evalsha", sha, "0"});
EXPECT_THAT(resp, IntArg(5));
resp = Run({"script", "load", " return 5 "});
EXPECT_EQ(resp, sha);
absl::AsciiStrToUpper(&sha);
resp = Run({"evalsha", sha, "0"});
EXPECT_THAT(resp, IntArg(5));
resp = Run({"evalsha", "foobar", "0"});
EXPECT_THAT(resp, ErrArg("No matching"));
resp = Run({"script", "load", "\n return 5"});
// Important to keep spaces in order to be compatible with Redis.
// See https://github.com/dragonflydb/dragonfly/issues/146
EXPECT_THAT(resp, "c6459b95a0e81df97af6fdd49b1a9e0287a57363");
}
TEST_F(DflyEngineTest, Memcache) {

View File

@ -702,7 +702,7 @@ void Service::Eval(CmdArgList args, ConnectionContext* cntx) {
CHECK(absl::SimpleAtoi(ArgS(args, 2), &num_keys)); // we already validated this
string_view body = ArgS(args, 1);
body = absl::StripAsciiWhitespace(body);
// body = absl::StripAsciiWhitespace(body);
if (body.empty()) {
return (*cntx)->SendNull();
@ -1042,8 +1042,8 @@ void Service::RegisterCommands() {
registry_ << CI{"QUIT", CO::READONLY | CO::FAST, 1, 0, 0, 0}.HFUNC(Quit)
<< CI{"MULTI", CO::NOSCRIPT | CO::FAST | CO::LOADING, 1, 0, 0, 0}.HFUNC(Multi)
<< CI{"DISCARD", CO::NOSCRIPT | CO::FAST | CO::LOADING, 1, 0, 0, 0}.MFUNC(Discard)
<< CI{"EVAL", CO::NOSCRIPT, -3, 0, 0, 0}.MFUNC(Eval).SetValidator(&EvalValidator)
<< CI{"EVALSHA", CO::NOSCRIPT, -3, 0, 0, 0}.MFUNC(EvalSha).SetValidator(&EvalValidator)
<< CI{"EVAL", CO::NOSCRIPT, -3, 3, 3, 1}.MFUNC(Eval).SetValidator(&EvalValidator)
<< CI{"EVALSHA", CO::NOSCRIPT, -3, 3, 3, 1}.MFUNC(EvalSha).SetValidator(&EvalValidator)
<< CI{"EXEC", kExecMask, 1, 0, 0, 0}.MFUNC(Exec)
<< CI{"PUBLISH", CO::LOADING | CO::FAST, 3, 0, 0, 0}.MFUNC(Publish)
<< CI{"SUBSCRIBE", CO::NOSCRIPT | CO::LOADING, -2, 0, 0, 0}.MFUNC(Subscribe)

View File

@ -53,10 +53,12 @@ void ScriptMgr::Run(CmdArgList args, ConnectionContext* cntx) {
if (subcmd == "LOAD" && args.size() == 2) {
string_view body = ArgS(args, 1);
body = absl::StripAsciiWhitespace(body);
if (body.empty())
return (*cntx)->SendError("Refuse to load empty script");
if (body.empty()) {
char sha[41];
Interpreter::FuncSha1(body, sha);
return (*cntx)->SendBulkString(sha);
}
Interpreter& interpreter = ServerState::tlocal()->GetInterpreter();
// no need to lock the interpreter since we do not mess the stack.