aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2017-06-15 15:03:39 -0400
committerTom Lane <tgl@sss.pgh.pa.us>2017-06-15 15:03:56 -0400
commit8e7d5845205e485328db4b7cb9b8411a96e95b80 (patch)
tree40c0682d45c400f08c23939a14f65f4ba9f650bf /src
parentad1ea61cf88a02f5983dff2d2342136a97675c29 (diff)
downloadpostgresql-8e7d5845205e485328db4b7cb9b8411a96e95b80.tar.gz
postgresql-8e7d5845205e485328db4b7cb9b8411a96e95b80.zip
Fix low-probability leaks of PGresult objects in the backend.
We had three occurrences of essentially the same coding pattern wherein we tried to retrieve a query result from a libpq connection without blocking. In the case where PQconsumeInput failed (typically indicating a lost connection), all three loops simply gave up and returned, forgetting to clear any previously-collected PGresult object. Since those are malloc'd not palloc'd, the oversight results in a process-lifespan memory leak. One instance, in libpqwalreceiver, is of little significance because the walreceiver process would just quit anyway if its connection fails. But we might as well fix it. The other two instances, in postgres_fdw, are somewhat more worrisome because at least in principle the scenario could be repeated, allowing the amount of memory leaked to build up to something worth worrying about. Moreover, in these cases the loops contain CHECK_FOR_INTERRUPTS calls, as well as other calls that could potentially elog(ERROR), providing another way to exit without having cleared the PGresult. Here we need to add PG_TRY logic similar to what exists in quite a few other places in postgres_fdw. Coverity noted the libpqwalreceiver bug; I found the other two cases by checking all calls of PQconsumeInput. Back-patch to all supported versions as appropriate (9.2 lacks postgres_fdw, so this is really quite unexciting for that branch). Discussion: https://postgr.es/m/22620.1497486981@sss.pgh.pa.us
Diffstat (limited to 'src')
-rw-r--r--src/backend/replication/libpqwalreceiver/libpqwalreceiver.c14
1 files changed, 10 insertions, 4 deletions
diff --git a/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c b/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c
index d101fa8c28d..d5d5757dd90 100644
--- a/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c
+++ b/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c
@@ -416,14 +416,20 @@ libpqrcv_PQexec(const char *query)
*/
if (!libpq_select(-1))
continue; /* interrupted */
+
+ /* Consume whatever data is available from the socket */
if (PQconsumeInput(streamConn) == 0)
- return NULL; /* trouble */
+ {
+ /* trouble; drop whatever we had and return NULL */
+ PQclear(lastResult);
+ return NULL;
+ }
}
/*
- * Emulate the PQexec()'s behavior of returning the last result when
- * there are many. Since walsender will never generate multiple
- * results, we skip the concatenation of error messages.
+ * Emulate PQexec()'s behavior of returning the last result when there
+ * are many. Since walsender will never generate multiple results, we
+ * skip the concatenation of error messages.
*/
result = PQgetResult(streamConn);
if (result == NULL)