]> 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:11 +0000 (16:25 +0900)
committerMichael Paquier <michael@paquier.xyz>
Thu, 19 Sep 2024 07:25:11 +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 6733f008fd55e28ad6dbb3b1d2a8de17beb45840..d0ae44232651184c1ef40b2b06ae8f35e7263077 100644 (file)
@@ -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)))
                {
index 3b0710a9e2e65c3b3820e2637c5c4c3b7782ba2e..80866849dbb603a17e1e3d8f45b1dc80441a41f3 100644 (file)
@@ -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.
index 812b94a9775685f3c39b845471329c3c89c2db50..8e6d09f8a60093f30fabead906f272b4a9704c79 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);