Tom Lane <t...@sss.pgh.pa.us> writes:
> Andrew Dunstan <and...@dunslane.net> writes:
>> ... Or maybe the 
>> postmaster needs to check the length somehow before it calls 
>> StreamServerPort() so we can give a saner error message.

> Hm.  That's ugly, but a lot less invasive than trying to get the
> official API to pass the information through.  Sounds like a plan to me.

Here's a patch for that --- I think we should apply and back-patch this.

                        regards, tom lane

diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 5e86987f221fee01c5049f925492e0f9c441d372..15a01a8324b8a6ff9727a1b02e7ba8fe385d3a39 100644
*** a/src/backend/libpq/pqcomm.c
--- b/src/backend/libpq/pqcomm.c
*************** StreamServerPort(int family, char *hostN
*** 308,313 ****
--- 308,321 ----
  		 * that file path
  		 */
  		UNIXSOCK_PATH(unixSocketPath, portNumber, unixSocketDir);
+ 		if (strlen(unixSocketPath) >= UNIXSOCK_PATH_BUFLEN)
+ 		{
+ 			ereport(LOG,
+ 					(errmsg("Unix-domain socket path \"%s\" is too long (maximum %d bytes)",
+ 							unixSocketPath,
+ 							(int) (UNIXSOCK_PATH_BUFLEN - 1))));
+ 			return STATUS_ERROR;
+ 		}
  		if (Lock_AF_UNIX(unixSocketDir, unixSocketPath) != STATUS_OK)
  			return STATUS_ERROR;
  		service = unixSocketPath;
diff --git a/src/include/libpq/pqcomm.h b/src/include/libpq/pqcomm.h
index 604b5535df6b24885b782688fee9ff7fd284746b..635132dec9317b4045108c75cd8c67a70c360968 100644
*** a/src/include/libpq/pqcomm.h
--- b/src/include/libpq/pqcomm.h
*************** typedef struct
*** 74,79 ****
--- 74,92 ----
  				(port))
  
  /*
+  * The maximum workable length of a socket path is what will fit into
+  * struct sockaddr_un.  This is usually only 100 or so bytes :-(.
+  *
+  * For consistency, always pass a MAXPGPATH-sized buffer to UNIXSOCK_PATH(),
+  * then complain if the resulting string is >= UNIXSOCK_PATH_BUFLEN bytes.
+  * (Because the standard API for getaddrinfo doesn't allow it to complain in
+  * a useful way when the socket pathname is too long, we have to test for
+  * this explicitly, instead of just letting the subroutine return an error.)
+  */
+ #define UNIXSOCK_PATH_BUFLEN sizeof(((struct sockaddr_un *) NULL)->sun_path)
+ 
+ 
+ /*
   * These manipulate the frontend/backend protocol version number.
   *
   * The major number should be incremented for incompatible changes.  The minor
diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c
index 9eaf41025beb652c6c242035490d93319a6bc5d0..1386bb791a96fab087af1ba33546ab89772327fd 100644
*** a/src/interfaces/libpq/fe-connect.c
--- b/src/interfaces/libpq/fe-connect.c
*************** static int
*** 1322,1328 ****
  connectDBStart(PGconn *conn)
  {
  	int			portnum;
! 	char		portstr[128];
  	struct addrinfo *addrs = NULL;
  	struct addrinfo hint;
  	const char *node;
--- 1322,1328 ----
  connectDBStart(PGconn *conn)
  {
  	int			portnum;
! 	char		portstr[MAXPGPATH];
  	struct addrinfo *addrs = NULL;
  	struct addrinfo hint;
  	const char *node;
*************** connectDBStart(PGconn *conn)
*** 1384,1389 ****
--- 1384,1398 ----
  		node = NULL;
  		hint.ai_family = AF_UNIX;
  		UNIXSOCK_PATH(portstr, portnum, conn->pgunixsocket);
+ 		if (strlen(portstr) >= UNIXSOCK_PATH_BUFLEN)
+ 		{
+ 			appendPQExpBuffer(&conn->errorMessage,
+ 							  libpq_gettext("Unix-domain socket path \"%s\" is too long (maximum %d bytes)\n"),
+ 											portstr,
+ 											(int) (UNIXSOCK_PATH_BUFLEN - 1));
+ 			conn->options_valid = false;
+ 			goto connect_errReturn;
+ 		}
  #else
  		/* Without Unix sockets, default to localhost instead */
  		node = DefaultHost;
-- 
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