psql: Fix memory leak with repeated calls of \bind
authorMichael Paquier
Thu, 19 Sep 2024 07:25:07 +0000 (16:25 +0900)
committerMichael Paquier
Thu, 19 Sep 2024 07:25:07 +0000 (16:25 +0900)
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
src/bin/psql/common.c
src/bin/psql/common.h

index 180781ecd05250c4aaf405884b76ccb63ebee9ae..4d2c81aa753cafc06cf5f6d519183a7c5a24c3e1 100644 (file)
@@ -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)))
        {
index fe8e049c4c1a243973d9be560ec001b78cce99aa..4a50eb1e672eff811611988d04f45ce04462e4b0 100644 (file)
@@ -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.
index 6efe12274fe593cf07cc209afbe9fbe74af62dcf..9baa1e890649197ae43c04c7f2984605bd16a67b 100644 (file)
@@ -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);