From b0ae6db2088bbd1d16733b359c9c300735e9c21e Mon Sep 17 00:00:00 2001 From: Michael Paquier Date: Thu, 19 Sep 2024 16:25:07 +0900 Subject: [PATCH] psql: Fix memory leak with repeated calls of \bind Calling \bind repeatedly would cause the memory allocated for the list of bind parameters to be leaked after each call, as the list is reset when beginning a single call. This issue is fixed by making the cleanup of the bind parameter list more aggressive, refactoring it into a single routine called after processing a query and before running an individual \bind. HEAD required more surgery and has been fixed by 87eeadaea143. Issue introduced by 5b66de3433e2. Reported-by: Anthonin Bonnefoy Discussion: https://postgr.es/m/2e5b89af-a351-ff0a-000c-037ac28314ab@gmail.com Backpatch-through: 16 --- src/bin/psql/command.c | 2 +- src/bin/psql/common.c | 29 +++++++++++++++++++++-------- src/bin/psql/common.h | 1 + 3 files changed, 23 insertions(+), 9 deletions(-) diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c index 180781ecd05..4d2c81aa753 100644 --- a/src/bin/psql/command.c +++ b/src/bin/psql/command.c @@ -471,7 +471,7 @@ exec_command_bind(PsqlScanState scan_state, bool active_branch) int nparams = 0; int nalloc = 0; - pset.bind_params = NULL; + clean_bind_state(); while ((opt = psql_scan_slash_option(scan_state, OT_NORMAL, NULL, false))) { diff --git a/src/bin/psql/common.c b/src/bin/psql/common.c index fe8e049c4c1..4a50eb1e672 100644 --- a/src/bin/psql/common.c +++ b/src/bin/psql/common.c @@ -1275,14 +1275,7 @@ sendquery_cleanup: } /* clean up after \bind */ - if (pset.bind_flag) - { - for (i = 0; i < pset.bind_nparams; i++) - free(pset.bind_params[i]); - free(pset.bind_params); - pset.bind_params = NULL; - pset.bind_flag = false; - } + clean_bind_state(); /* reset \gset trigger */ if (pset.gset_prefix) @@ -2252,6 +2245,26 @@ uri_prefix_length(const char *connstr) return 0; } +/* + * Reset state related to \bind + * + * Clean up any state related to bind parameters and bind_flag. This needs + * to be called after processing a query or when running \bind. + */ +void +clean_bind_state(void) +{ + if (pset.bind_flag) + { + for (int i = 0; i < pset.bind_nparams; i++) + free(pset.bind_params[i]); + free(pset.bind_params); + } + + pset.bind_params = NULL; + pset.bind_flag = false; +} + /* * Recognized connection string either starts with a valid URI prefix or * contains a "=" in it. diff --git a/src/bin/psql/common.h b/src/bin/psql/common.h index 6efe12274fe..9baa1e89064 100644 --- a/src/bin/psql/common.h +++ b/src/bin/psql/common.h @@ -41,6 +41,7 @@ extern bool standard_strings(void); extern const char *session_username(void); extern void expand_tilde(char **filename); +extern void clean_bind_state(void); extern bool recognized_connection_string(const char *connstr); -- 2.39.5