/* This gets called when the function "client)" gets called in Lua */ int luaCall_client(lua_State *L) { LuaFlag = PIPE_NONE_FLAG; int argc = lua_gettop(L); const char *arg1 = lua_tostring(L, 1); if (!arg1) { return redisLuaArityErr(L, NULL); } redisCommand *cmd = lookupCommand((char *)arg1); if (!cmd) { char buf[64]; snprintf(buf, 63, "-ERR Unknown command '%s'\r\n", arg1); buf[63] = '\0'; lua_pushstring(L, buf); LuaFlag = PIPE_ONE_LINER_FLAG; return 1; } else if ((cmd->arity > 0 && cmd->arity != argc) || (argc < -cmd->arity)) { return redisLuaArityErr(L, cmd->name); } if (server.maxmemory && (cmd->flags & REDIS_CMD_DENYOOM) && (zmalloc_used_memory() > server.maxmemory)) { LuaFlag = PIPE_ONE_LINER_FLAG; lua_pushstring(L, "-ERR command not allowed when used memory > 'maxmemory'\r\n"); return 1; } if (server.vm_enabled && server.vm_max_threads > 0 && blockClientOnSwappedKeys(LuaClient, cmd)) return 1; long ok = 0; /* must come before first GOTO */ redisClient *rfc = rsql_createFakeClient(); robj **rargv = zmalloc(sizeof(robj *) * argc); for (int i = 0; i < argc; i++) { char *arg = (char *)lua_tostring(L, i + 1); if (!arg) { char *lbuf = "args must be strings"; luaL_argerror (L, i, lbuf); LuaFlag = PIPE_ONE_LINER_FLAG; ok = 1; goto redis_lua_end; } rargv[i] = _createStringObject(arg); } rfc->argv = rargv; rfc->argc = argc; ok = fakeClientPipe(LuaClient, rfc, L, 0, &LuaFlag, luaLine, emptyNoop); redis_lua_end: for (int i = 0; i < argc; i++) decrRefCount(rargv[i]); zfree(rargv); rsql_freeFakeClient(rfc); return (ok > 0) ? 1 : 0; }
static void runCmdInFakeClient(sds s) { //RL4 "runCmdInFakeClient: %s", s); int argc; sds *argv = sdssplitlen(s, sdslen(s), " ", 1, &argc); // FREEME 017 if (!argv) return; if (argc < 1) goto run_cmd_end; redisCommand *cmd = lookupCommand(argv[0]); if (!cmd) goto run_cmd_end; if ((cmd->arity > 0 && cmd->arity > argc) || (argc < -cmd->arity)) goto run_cmd_end; int arity; robj **rargv; if (cmd->arity > 0 || cmd->proc == insertCommand || cmd->proc == sqlSelectCommand || cmd->proc == tscanCommand) { arity = abs(cmd->arity); rargv = zmalloc(sizeof(robj *) * arity); /* ZFREE ME 018 */ for (int j = 0; j < arity - 1; j++) { rargv[j] = createStringObject(argv[j], sdslen(argv[j])); // FREE 019 } sds lastarg = sdsempty(); for (int j = arity - 1; j < argc; j++) { if (j != (arity - 1)) lastarg = sdscatlen(lastarg, " ", 1); lastarg = sdscatlen(lastarg, argv[j], sdslen(argv[j])); } rargv[arity - 1] = createObject(REDIS_STRING, lastarg); // FREE 019 } else { arity = argc; rargv = zmalloc(sizeof(robj *) * arity); /* ZFREE ME 018 */ for (int j = 0; j < arity; j++) { rargv[j] = createStringObject(argv[j], sdslen(argv[j])); // FREE 019 } } redisClient *c = CurrClient; redisClient *fc = rsql_createFakeClient(); /* DESTROY ME 020 */ fc->argv = rargv; fc->argc = arity; fakeClientPipe(c, fc, NULL, 0, &NriFlag, nonRelIndRespHandler, emptyNonRelIndRespHandler); rsql_freeFakeClient(fc); /* DESTROYED 020 */ for (int j = 0; j < arity; j++) decrRefCount(rargv[j]); /* FREED 019 */ zfree(rargv); /* ZFREED 018 */ run_cmd_end: for (int j = 0; j < argc; j++) sdsfree(argv[j]); /* FREED 017 */ zfree(argv); /* FREED 017 */ }
/* TODO the protocol-parsing does not exactly follow the line protocol, it follow what the code does ... the code could change */ void createTableAsObjectOperation(redisClient *c, bool is_ins) { robj *wargv[3]; struct redisClient *wfc = rsql_createFakeClient(); /* client to write */ wfc->argc = 3; wfc->argv = wargv; wfc->argv[1] = c->argv[2]; /* table name */ robj **rargv = malloc(sizeof(robj *) * c->argc); struct redisClient *rfc = rsql_createFakeClient(); /* client to read */ rfc->argv = rargv; for (int i = 4; i < c->argc; i++) { rfc->argv[i - 4] = c->argv[i]; } rfc->argc = c->argc - 4; rfc->db = c->db; fakeClientPipe(c, rfc, wfc, is_ins, addSingle); rsql_freeFakeClient(rfc); rsql_freeFakeClient(wfc); free(rargv); addReply(c, shared.ok); return; }