Fix assorted resource leaks in new pg_createsubscriber code.
authorTom Lane <[email protected]>
Mon, 1 Apr 2024 17:47:27 +0000 (13:47 -0400)
committerTom Lane <[email protected]>
Mon, 1 Apr 2024 17:47:49 +0000 (13:47 -0400)
Various error paths did not release resources before returning.
While it's likely that the program would just exit shortly later,
none of the functions in question have summary exit(1) calls,
so they should not be assuming that.

Ranier Vilela and Tom Lane, per reports from Coverity

Discussion: https://postgr.es/m/CAEudQAr2_SZFxB4kXJiL4+2UaNZxUk5UBJtj0oXyJYMGZu-03g@mail.gmail.com

src/bin/pg_basebackup/pg_createsubscriber.c

index a6e09866705a27be8acf091ad3e8841829df91b1..90cc580811dfe0c97e2b7ad6191d0e1dbbee0eeb 100644 (file)
@@ -251,8 +251,8 @@ usage(void)
 static char *
 get_base_conninfo(const char *conninfo, char **dbname)
 {
-   PQExpBuffer buf = createPQExpBuffer();
-   PQconninfoOption *conn_opts = NULL;
+   PQExpBuffer buf;
+   PQconninfoOption *conn_opts;
    PQconninfoOption *conn_opt;
    char       *errmsg = NULL;
    char       *ret;
@@ -262,9 +262,11 @@ get_base_conninfo(const char *conninfo, char **dbname)
    if (conn_opts == NULL)
    {
        pg_log_error("could not parse connection string: %s", errmsg);
+       PQfreemem(errmsg);
        return NULL;
    }
 
+   buf = createPQExpBuffer();
    i = 0;
    for (conn_opt = conn_opts; conn_opt->keyword != NULL; conn_opt++)
    {
@@ -497,9 +499,10 @@ connect_database(const char *conninfo, bool exit_on_error)
    {
        pg_log_error("connection to database failed: %s",
                     PQerrorMessage(conn));
+       PQfinish(conn);
+
        if (exit_on_error)
            exit(1);
-
        return NULL;
    }
 
@@ -509,9 +512,11 @@ connect_database(const char *conninfo, bool exit_on_error)
    {
        pg_log_error("could not clear search_path: %s",
                     PQresultErrorMessage(res));
+       PQclear(res);
+       PQfinish(conn);
+
        if (exit_on_error)
            exit(1);
-
        return NULL;
    }
    PQclear(res);
@@ -941,6 +946,8 @@ check_publisher(const struct LogicalRepInfo *dbinfo)
        failed = true;
    }
 
+   pg_free(wal_level);
+
    if (failed)
        exit(1);
 }
@@ -1209,6 +1216,8 @@ create_logical_replication_slot(PGconn *conn, struct LogicalRepInfo *dbinfo)
            pg_log_error("could not create replication slot \"%s\" on database \"%s\": %s",
                         slot_name, dbinfo->dbname,
                         PQresultErrorMessage(res));
+           PQclear(res);
+           destroyPQExpBuffer(str);
            return NULL;
        }