From 16a61884b5956778cae64a5746f4cdd9ae1ae01b Mon Sep 17 00:00:00 2001 From: Peter Eisentraut Date: Mon, 23 Jan 2017 11:06:30 -0500 Subject: [PATCH] Fix memory leaks in libpqwalreceiver The results of the libpq functions PQescapeIdentifier() and PQescapeLiteral() must be freed explicitly. Also handle errors in these functions better. --- .../libpqwalreceiver/libpqwalreceiver.c | 32 +++++++++++++++---- 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c b/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c index 7df3698afb..44a89c73fd 100644 --- a/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c +++ b/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c @@ -304,17 +304,30 @@ libpqrcv_startstreaming(WalReceiverConn *conn, { char *pubnames_str; List *pubnames; + char *pubnames_literal; appendStringInfoString(&cmd, " ("); + appendStringInfo(&cmd, "proto_version '%u'", options->proto.logical.proto_version); + pubnames = options->proto.logical.publication_names; pubnames_str = stringlist_to_identifierstr(conn->streamConn, pubnames); - appendStringInfo(&cmd, ", publication_names %s", - PQescapeLiteral(conn->streamConn, pubnames_str, - strlen(pubnames_str))); - appendStringInfoChar(&cmd, ')'); + if (!pubnames_str) + ereport(ERROR, + (errmsg("could not start WAL streaming: %s", + PQerrorMessage(conn->streamConn)))); + pubnames_literal = PQescapeLiteral(conn->streamConn, pubnames_str, + strlen(pubnames_str)); + if (!pubnames_literal) + ereport(ERROR, + (errmsg("could not start WAL streaming: %s", + PQerrorMessage(conn->streamConn)))); + appendStringInfo(&cmd, ", publication_names %s", pubnames_literal); + PQfreemem(pubnames_literal); pfree(pubnames_str); + + appendStringInfoChar(&cmd, ')'); } else appendStringInfo(&cmd, " TIMELINE %u", @@ -736,14 +749,21 @@ stringlist_to_identifierstr(PGconn *conn, List *strings) foreach (lc, strings) { char *val = strVal(lfirst(lc)); + char *val_escaped; if (first) first = false; else appendStringInfoChar(&res, ','); - appendStringInfoString(&res, - PQescapeIdentifier(conn, val, strlen(val))); + val_escaped = PQescapeIdentifier(conn, val, strlen(val)); + if (!val_escaped) + { + free(res.data); + return NULL; + } + appendStringInfoString(&res, val_escaped); + PQfreemem(val_escaped); } return res.data;