pgpool2.git / summary / log / commit / refs
commit bd43f099441b2d49b90ac7b462fdc3c092fe292e
Author: Tatsuo Ishii <ishii@postgresql.org>
Date: Tue Nov 26 07:30:51 2013 +0000
Fix resource leak in make_persistent_db_connection.
For this pupose, new static function
free_persisten_db_connection_memory is added.
Per Coverity report #1111468.
src/protocol/child.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++-----
1 file changed, 49 insertions(+), 5 deletions(-)
diff --git a/src/protocol/child.c b/src/protocol/child.c
index 5767b254a..33f3273e7 100644
--- a/src/protocol/child.c
+++ b/src/protocol/child.c
@@ -75,6 +75,8 @@ static void init_system_db_connection(void);
static bool connect_using_existing_connection(POOL_CONNECTION *frontend,
POOL_CONNECTION_POOL *backend,
StartupPacket *sp);
+static void free_persisten_db_connection_memory(POOL_CONNECTION_POOL_SLOT *cp);
+
/*
* non 0 means SIGTERM(smart shutdown) or SIGINT(fast shutdown) has arrived
*/
@@ -1490,6 +1492,7 @@ POOL_CONNECTION_POOL_SLOT *make_persistent_db_connection(
if (startup_packet == NULL)
{
pool_error("make_persistent_db_connection: could not allocate memory");
+ free_persisten_db_connection_memory(cp);
return NULL;
}
memset(startup_packet, 0, sizeof(*startup_packet));
@@ -1510,6 +1513,8 @@ POOL_CONNECTION_POOL_SLOT *make_persistent_db_connection(
if (fd < 0)
{
pool_error("make_persistent_db_connection: connection to %s(%d) failed", hostname, port);
+ free_persisten_db_connection_memory(cp);
+ free(startup_packet);
return NULL;
}
@@ -1526,6 +1531,9 @@ POOL_CONNECTION_POOL_SLOT *make_persistent_db_connection(
if (len1 >= (sizeof(startup_packet->data)-len))
{
pool_error("make_persistent_db_connection: too long user name");
+ pool_close(cp->con);
+ free_persisten_db_connection_memory(cp);
+ free(startup_packet);
return NULL;
}
@@ -1534,6 +1542,9 @@ POOL_CONNECTION_POOL_SLOT *make_persistent_db_connection(
if (len1 >= (sizeof(startup_packet->data)-len))
{
pool_error("make_persistent_db_connection: too long user name");
+ pool_close(cp->con);
+ free_persisten_db_connection_memory(cp);
+ free(startup_packet);
return NULL;
}
@@ -1542,6 +1553,9 @@ POOL_CONNECTION_POOL_SLOT *make_persistent_db_connection(
if (len1 >= (sizeof(startup_packet->data)-len))
{
pool_error("make_persistent_db_connection: too long database name");
+ pool_close(cp->con);
+ free_persisten_db_connection_memory(cp);
+ free(startup_packet);
return NULL;
}
len += len1;
@@ -1551,6 +1565,9 @@ POOL_CONNECTION_POOL_SLOT *make_persistent_db_connection(
if (cp->sp == NULL)
{
pool_error("make_persistent_db_connection: could not allocate memory");
+ pool_close(cp->con);
+ free_persisten_db_connection_memory(cp);
+ free(startup_packet);
return NULL;
}
@@ -1562,12 +1579,16 @@ POOL_CONNECTION_POOL_SLOT *make_persistent_db_connection(
if (cp->sp->database == NULL)
{
pool_error("make_persistent_db_connection: could not allocate memory");
+ pool_close(cp->con);
+ free_persisten_db_connection_memory(cp);
return NULL;
}
cp->sp->user = strdup(user);
if (cp->sp->user == NULL)
{
pool_error("make_persistent_db_connection: could not allocate memory");
+ pool_close(cp->con);
+ free_persisten_db_connection_memory(cp);
return NULL;
}
@@ -1578,6 +1599,8 @@ POOL_CONNECTION_POOL_SLOT *make_persistent_db_connection(
if (status)
{
pool_error("make_persistent_db_connection: send_startup_packet failed");
+ pool_close(cp->con);
+ free_persisten_db_connection_memory(cp);
return NULL;
}
@@ -1587,12 +1610,37 @@ POOL_CONNECTION_POOL_SLOT *make_persistent_db_connection(
if (s_do_auth(cp, password))
{
pool_error("make_persistent_db_connection: s_do_auth failed");
+ pool_close(cp->con);
+ free_persisten_db_connection_memory(cp);
return NULL;
}
return cp;
}
+/*
+ * Free memory of POOL_CONNECTION_POOL_SLOT. Should only be used in
+ * make_persistent_db_connection and discard_persistent_db_connection.
+ */
+void free_persisten_db_connection_memory(POOL_CONNECTION_POOL_SLOT *cp)
+{
+ if (!cp)
+ return;
+ if (!cp->sp)
+ {
+ free(cp);
+ return;
+ }
+ if (cp->sp->startup_packet)
+ free(cp->sp->startup_packet);
+ if (cp->sp->database)
+ free(cp->sp->database);
+ if (cp->sp->user)
+ free(cp->sp->user);
+ free(cp->sp);
+ free(cp);
+}
+
/*
* Discard connection and memory allocated by
* make_persistent_db_connection().
@@ -1620,11 +1668,7 @@ void discard_persistent_db_connection(POOL_CONNECTION_POOL_SLOT *cp)
pool_unset_nonblock(cp->con->fd);
pool_close(cp->con);
- free(cp->sp->startup_packet);
- free(cp->sp->database);
- free(cp->sp->user);
- free(cp->sp);
- free(cp);
+ free_persisten_db_connection_memory(cp);
}
/*
[parent: 4cc91f5d811f]