Skip to content

Commit b7ab88d

Browse files
committed
Fix assorted new memory leaks in libpq.
Valgrind'ing the postgres_fdw tests showed me that libpq was leaking PGconn.be_cancel_key. It looks like freePGconn is expecting pqDropServerData to release it ... but in a cancel connection object, that doesn't happen. Looking a little closer, I was dismayed to find that freePGconn also missed freeing the pgservice, min_protocol_version, max_protocol_version, sslkeylogfile, scram_client_key_binary, and scram_server_key_binary strings. There's much less excuse for those oversights. Worse, that's from five different commits (a460251, 4b99fed, 285613c, 2da74d8, 761c795), some of them by extremely senior hackers. Fortunately, all of these are new in v18, so we haven't shipped any leaky versions of libpq. While at it, reorder the operations in freePGconn to match the order of the fields in struct PGconn. Some of those free's seem to have been inserted with the aid of a dartboard.
1 parent cb14564 commit b7ab88d

File tree

1 file changed

+24
-20
lines changed

1 file changed

+24
-20
lines changed

src/interfaces/libpq/fe-connect.c

Lines changed: 24 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2027,13 +2027,11 @@ pqConnectOptions2(PGconn *conn)
20272027
if (len < 0)
20282028
{
20292029
libpq_append_conn_error(conn, "invalid SCRAM client key");
2030-
free(conn->scram_client_key_binary);
20312030
return false;
20322031
}
20332032
if (len != SCRAM_MAX_KEY_LEN)
20342033
{
20352034
libpq_append_conn_error(conn, "invalid SCRAM client key length: %d", len);
2036-
free(conn->scram_client_key_binary);
20372035
return false;
20382036
}
20392037
conn->scram_client_key_len = len;
@@ -2052,13 +2050,11 @@ pqConnectOptions2(PGconn *conn)
20522050
if (len < 0)
20532051
{
20542052
libpq_append_conn_error(conn, "invalid SCRAM server key");
2055-
free(conn->scram_server_key_binary);
20562053
return false;
20572054
}
20582055
if (len != SCRAM_MAX_KEY_LEN)
20592056
{
20602057
libpq_append_conn_error(conn, "invalid SCRAM server key length: %d", len);
2061-
free(conn->scram_server_key_binary);
20622058
return false;
20632059
}
20642060
conn->scram_server_key_len = len;
@@ -5053,21 +5049,19 @@ freePGconn(PGconn *conn)
50535049
free(conn->events[i].name);
50545050
}
50555051

5056-
release_conn_addrinfo(conn);
5057-
pqReleaseConnHosts(conn);
5058-
5059-
free(conn->client_encoding_initial);
5060-
free(conn->events);
5052+
/* free everything not freed in pqClosePGconn */
50615053
free(conn->pghost);
50625054
free(conn->pghostaddr);
50635055
free(conn->pgport);
50645056
free(conn->connect_timeout);
50655057
free(conn->pgtcp_user_timeout);
5058+
free(conn->client_encoding_initial);
50665059
free(conn->pgoptions);
50675060
free(conn->appname);
50685061
free(conn->fbappname);
50695062
free(conn->dbName);
50705063
free(conn->replication);
5064+
free(conn->pgservice);
50715065
free(conn->pguser);
50725066
if (conn->pgpass)
50735067
{
@@ -5082,8 +5076,9 @@ freePGconn(PGconn *conn)
50825076
free(conn->keepalives_count);
50835077
free(conn->sslmode);
50845078
free(conn->sslnegotiation);
5085-
free(conn->sslcert);
5079+
free(conn->sslcompression);
50865080
free(conn->sslkey);
5081+
free(conn->sslcert);
50875082
if (conn->sslpassword)
50885083
{
50895084
explicit_bzero(conn->sslpassword, strlen(conn->sslpassword));
@@ -5093,32 +5088,40 @@ freePGconn(PGconn *conn)
50935088
free(conn->sslrootcert);
50945089
free(conn->sslcrl);
50955090
free(conn->sslcrldir);
5096-
free(conn->sslcompression);
50975091
free(conn->sslsni);
50985092
free(conn->requirepeer);
5099-
free(conn->require_auth);
5100-
free(conn->ssl_min_protocol_version);
5101-
free(conn->ssl_max_protocol_version);
51025093
free(conn->gssencmode);
51035094
free(conn->krbsrvname);
51045095
free(conn->gsslib);
51055096
free(conn->gssdelegation);
5106-
free(conn->connip);
5107-
/* Note that conn->Pfdebug is not ours to close or free */
5108-
free(conn->write_err_msg);
5109-
free(conn->inBuffer);
5110-
free(conn->outBuffer);
5111-
free(conn->rowBuf);
5097+
free(conn->min_protocol_version);
5098+
free(conn->max_protocol_version);
5099+
free(conn->ssl_min_protocol_version);
5100+
free(conn->ssl_max_protocol_version);
51125101
free(conn->target_session_attrs);
5102+
free(conn->require_auth);
51135103
free(conn->load_balance_hosts);
51145104
free(conn->scram_client_key);
51155105
free(conn->scram_server_key);
5106+
free(conn->sslkeylogfile);
51165107
free(conn->oauth_issuer);
51175108
free(conn->oauth_issuer_id);
51185109
free(conn->oauth_discovery_uri);
51195110
free(conn->oauth_client_id);
51205111
free(conn->oauth_client_secret);
51215112
free(conn->oauth_scope);
5113+
/* Note that conn->Pfdebug is not ours to close or free */
5114+
free(conn->events);
5115+
pqReleaseConnHosts(conn);
5116+
free(conn->connip);
5117+
release_conn_addrinfo(conn);
5118+
free(conn->scram_client_key_binary);
5119+
free(conn->scram_server_key_binary);
5120+
/* if this is a cancel connection, be_cancel_key may still be allocated */
5121+
free(conn->be_cancel_key);
5122+
free(conn->inBuffer);
5123+
free(conn->outBuffer);
5124+
free(conn->rowBuf);
51225125
termPQExpBuffer(&conn->errorMessage);
51235126
termPQExpBuffer(&conn->workBuffer);
51245127

@@ -5147,6 +5150,7 @@ pqReleaseConnHosts(PGconn *conn)
51475150
}
51485151
}
51495152
free(conn->connhost);
5153+
conn->connhost = NULL;
51505154
}
51515155
}
51525156

0 commit comments

Comments
 (0)