From fc3956e8f4d35ea66967bb26f26175ad184f8978 Mon Sep 17 00:00:00 2001 From: Binbin Date: Thu, 18 Aug 2022 17:36:01 +0800 Subject: [PATCH] Fix memory leak in moduleFreeCommand (#11147) Currently, we call zfree(cmd->args), but the argument array needs to be freed recursively (there might be sub-args). Also fixed memory leaks on cmd->tips and cmd->history. Fixes #11145 --- src/module.c | 19 ++++++++++++++++++- tests/unit/moduleapi/cmdintrospection.tcl | 4 ++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/src/module.c b/src/module.c index 5db88703f..43394e2f2 100644 --- a/src/module.c +++ b/src/module.c @@ -11039,6 +11039,21 @@ void moduleFreeModuleStructure(struct RedisModule *module) { zfree(module); } +void moduleFreeArgs(struct redisCommandArg *args, int num_args) { + for (int j = 0; j < num_args; j++) { + zfree((char *)args[j].name); + zfree((char *)args[j].token); + zfree((char *)args[j].summary); + zfree((char *)args[j].since); + zfree((char *)args[j].deprecated_since); + + if (args[j].subargs) { + moduleFreeArgs(args[j].subargs, args[j].num_args); + } + } + zfree(args); +} + /* Free the command registered with the specified module. * On success C_OK is returned, otherwise C_ERR is returned. * @@ -11064,10 +11079,12 @@ int moduleFreeCommand(struct RedisModule *module, struct redisCommand *cmd) { zfree(cmd->key_specs); for (int j = 0; cmd->tips && cmd->tips[j]; j++) zfree((char *)cmd->tips[j]); + zfree(cmd->tips); for (int j = 0; cmd->history && cmd->history[j].since; j++) { zfree((char *)cmd->history[j].since); zfree((char *)cmd->history[j].changes); } + zfree(cmd->history); zfree((char *)cmd->summary); zfree((char *)cmd->since); zfree((char *)cmd->deprecated_since); @@ -11076,7 +11093,7 @@ int moduleFreeCommand(struct RedisModule *module, struct redisCommand *cmd) { hdr_close(cmd->latency_histogram); cmd->latency_histogram = NULL; } - zfree(cmd->args); + moduleFreeArgs(cmd->args, cmd->num_args); zfree(cp); if (cmd->subcommands_dict) { diff --git a/tests/unit/moduleapi/cmdintrospection.tcl b/tests/unit/moduleapi/cmdintrospection.tcl index 8ac49ed9f..4d67af1e1 100644 --- a/tests/unit/moduleapi/cmdintrospection.tcl +++ b/tests/unit/moduleapi/cmdintrospection.tcl @@ -40,4 +40,8 @@ start_server {tags {"modules"}} { assert_equal $redis_reply $module_reply } + + test "Unload the module - cmdintrospection" { + assert_equal {OK} [r module unload cmdintrospection] + } }