]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
psql: Fix memory leak with repeated calls of \bind
authorMichael Paquier <michael@paquier.xyz>
Thu, 19 Sep 2024 07:25:07 +0000 (16:25 +0900)
committerMichael Paquier <michael@paquier.xyz>
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);