On 11/24/2016 10:38 PM, Andreas Karlsson wrote:
To me it feels like the proper fix would be to make PQHost() return the
value of the host parameter rather than the hostaddr (maybe add a new
field in the pg_conn_host struct). But would be a behaviour change which
might break someones application. Thoughts?

I have attached a proof of concept patch for this. Remaining work is investigating all the callers of PQhost() and see if any of them are negatively affected by this patch and cleaning up the code some.

Andreas
diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c
index 3e9c45b..39c11eb 100644
--- a/src/interfaces/libpq/fe-connect.c
+++ b/src/interfaces/libpq/fe-connect.c
@@ -798,8 +798,34 @@ connectOptions2(PGconn *conn)
 	 */
 	if (conn->pghostaddr != NULL && conn->pghostaddr[0] != '\0')
 	{
-		conn->connhost[0].host = strdup(conn->pghostaddr);
-		if (conn->connhost[0].host == NULL)
+		if (conn->pghost != NULL && conn->pghost[0] != '\0')
+		{
+			char *e = conn->pghost;
+
+			/*
+			 * Search for the end of the first hostname; a comma or
+			 * end-of-string acts as a terminator.
+			 */
+			while (*e != '\0' && *e != ',')
+				++e;
+
+			/* Copy the hostname whose bounds we just identified. */
+			conn->connhost[0].host =
+				(char *) malloc(sizeof(char) * (e - conn->pghost + 1));
+			if (conn->connhost[0].host == NULL)
+				goto oom_error;
+			memcpy(conn->connhost[0].host, conn->pghost, e - conn->pghost);
+			conn->connhost[0].host[e - conn->pghost] = '\0';
+		}
+		else
+		{
+			conn->connhost[0].host = strdup(conn->pghostaddr);
+			if (conn->connhost[0].host == NULL)
+				goto oom_error;
+		}
+
+		conn->connhost[0].hostaddr = strdup(conn->pghostaddr);
+		if (conn->connhost[0].hostaddr == NULL)
 			goto oom_error;
 		conn->connhost[0].type = CHT_HOST_ADDRESS;
 	}
@@ -827,6 +853,10 @@ connectOptions2(PGconn *conn)
 			memcpy(conn->connhost[i].host, s, e - s);
 			conn->connhost[i].host[e - s] = '\0';
 
+			conn->connhost[i].hostaddr = strdup(conn->connhost[i].host);
+			if (conn->connhost[i].hostaddr == NULL)
+				goto oom_error;
+
 			/* Identify the type of host. */
 			conn->connhost[i].type = CHT_HOST_NAME;
 #ifdef HAVE_UNIX_SOCKETS
@@ -845,12 +875,14 @@ connectOptions2(PGconn *conn)
 	{
 #ifdef HAVE_UNIX_SOCKETS
 		conn->connhost[0].host = strdup(DEFAULT_PGSOCKET_DIR);
+		conn->connhost[0].hostaddr = strdup(DEFAULT_PGSOCKET_DIR);
 		conn->connhost[0].type = CHT_UNIX_SOCKET;
 #else
 		conn->connhost[0].host = strdup(DefaultHost);
+		conn->connhost[0].hostaddr = strdup(DefaultHost);
 		conn->connhost[0].type = CHT_HOST_NAME;
 #endif
-		if (conn->connhost[0].host == NULL)
+		if (conn->connhost[0].host == NULL || conn->connhost[0].hostaddr == NULL)
 			goto oom_error;
 	}
 
@@ -1547,7 +1579,7 @@ connectDBStart(PGconn *conn)
 	for (i = 0; i < conn->nconnhost; ++i)
 	{
 		pg_conn_host *ch = &conn->connhost[i];
-		char	   *node = ch->host;
+		char	   *node = ch->hostaddr;
 		struct addrinfo hint;
 		int			thisport;
 
@@ -3034,6 +3066,8 @@ freePGconn(PGconn *conn)
 		{
 			if (conn->connhost[i].host != NULL)
 				free(conn->connhost[i].host);
+			if (conn->connhost[i].hostaddr != NULL)
+				free(conn->connhost[i].hostaddr);
 			if (conn->connhost[i].port != NULL)
 				free(conn->connhost[i].port);
 			if (conn->connhost[i].password != NULL)
diff --git a/src/interfaces/libpq/libpq-int.h b/src/interfaces/libpq/libpq-int.h
index 854ec89..19e3a5e 100644
--- a/src/interfaces/libpq/libpq-int.h
+++ b/src/interfaces/libpq/libpq-int.h
@@ -306,7 +306,10 @@ typedef enum pg_conn_host_type
  */
 typedef struct pg_conn_host
 {
-	char	   *host;			/* host name or address, or socket path */
+	char	   *host;			/* host name or address, or socket path,
+								 * used for validating the hostname */
+	char	   *hostaddr;		/* host name or address, or socket path,
+								 * used when actually connecting */
 	pg_conn_host_type type;		/* type of host */
 	char	   *port;			/* port number for this host; if not NULL,
 								 * overrrides the PGConn's pgport */
-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to