postgres.git / summary / log / commit / refs

commit    c2fb2f9e200f43133e4d910d4d9c27cf5e1bb29d
Author:   Michael Paquier <michael@paquier.xyz>
Date:     Thu Sep 19 07:25:11 2024 +0000
First released in: 16.5, 17.0

    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 6733f008fd5..d0ae4423265 100644 --- a/src/bin/psql/command.c +++ b/src/bin/psql/command.c @@ -470,7 +470,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 3b0710a9e2e..80866849dbb 100644 --- a/src/bin/psql/common.c +++ b/src/bin/psql/common.c @@ -1241,14 +1241,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) @@ -2413,6 +2406,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 812b94a9775..8e6d09f8a60 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); [parent: 00c8c4180a38]