From 1ef014ee6b0ca385451cc74e3cb2da9048975c7e Mon Sep 17 00:00:00 2001 From: Wang Yuan Date: Sat, 8 Aug 2020 19:36:41 +0800 Subject: [PATCH] Fix applying zero offset to null pointer when creating moduleFreeContextReusedClient (#7323) Before this fix we where attempting to select a db before creating db the DB, see: #7323 This issue doesn't seem to have any implications, since the selected DB index is 0, the db pointer remains NULL, and will later be correctly set before using this dummy client for the first time. As we know, we call 'moduleInitModulesSystem()' before 'initServer()'. We will allocate memory for server.db in 'initServer', but we call 'createClient()' that will call 'selectDb()' in 'moduleInitModulesSystem()', before the databases where created. Instead, we should call 'createClient()' for moduleFreeContextReusedClient after 'initServer()'. --- src/module.c | 15 +++++++++++---- src/server.c | 1 + src/server.h | 1 + 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/module.c b/src/module.c index b008929f7..e0309ae6b 100644 --- a/src/module.c +++ b/src/module.c @@ -283,7 +283,7 @@ typedef struct RedisModuleKeyspaceSubscriber { static list *moduleKeyspaceSubscribers; /* Static client recycled for when we need to provide a context with a client - * in a situation where there is no client to provide. This avoidsallocating + * in a situation where there is no client to provide. This avoids allocating * a new client per round. For instance this is used in the keyspace * notifications, timers and cluster messages callbacks. */ static client *moduleFreeContextReusedClient; @@ -7249,6 +7249,16 @@ int moduleRegisterApi(const char *funcname, void *funcptr) { /* Global initialization at Redis startup. */ void moduleRegisterCoreAPI(void); +/* Some steps in module initialization need to be done last after server + * initialization. + * For example, selectDb() in createClient() requires that server.db has + * been initialized, see #7323. */ +void moduleInitModulesSystemLast(void) { + moduleFreeContextReusedClient = createClient(NULL); + moduleFreeContextReusedClient->flags |= CLIENT_MODULE; + moduleFreeContextReusedClient->user = NULL; /* root user. */ +} + void moduleInitModulesSystem(void) { moduleUnblockedClients = listCreate(); server.loadmodule_queue = listCreate(); @@ -7256,9 +7266,6 @@ void moduleInitModulesSystem(void) { /* Set up the keyspace notification susbscriber list and static client */ moduleKeyspaceSubscribers = listCreate(); - moduleFreeContextReusedClient = createClient(NULL); - moduleFreeContextReusedClient->flags |= CLIENT_MODULE; - moduleFreeContextReusedClient->user = NULL; /* root user. */ /* Set up filter list */ moduleCommandFilters = listCreate(); diff --git a/src/server.c b/src/server.c index c9d995e0b..b23aa3cf0 100644 --- a/src/server.c +++ b/src/server.c @@ -5205,6 +5205,7 @@ int main(int argc, char **argv) { #ifdef __linux__ linuxMemoryWarnings(); #endif + moduleInitModulesSystemLast(); moduleLoadFromQueue(); ACLLoadUsersAtStartup(); InitServerLast(); diff --git a/src/server.h b/src/server.h index 71bbfec7b..19aab8750 100644 --- a/src/server.h +++ b/src/server.h @@ -1572,6 +1572,7 @@ extern dictType modulesDictType; /* Modules */ void moduleInitModulesSystem(void); +void moduleInitModulesSystemLast(void); int moduleLoad(const char *path, void **argv, int argc); void moduleLoadFromQueue(void); int *moduleGetCommandKeysViaAPI(struct redisCommand *cmd, robj **argv, int argc, int *numkeys);