Skip to content

Commit 31c341a

Browse files
committed
Produce a more useful error message for over-length Unix socket paths.
The length of a socket path name is constrained by the size of struct sockaddr_un, and there's not a lot we can do about it since that is a kernel API. However, it would be a good thing if we produced an intelligible error message when the user specifies a socket path that's too long --- and getaddrinfo's standard API is too impoverished to do this in the natural way. So insert explicit tests at the places where we construct a socket path name. Now you'll get an error that makes sense and even tells you what the limit is, rather than something generic like "Non-recoverable failure in name resolution". Per trouble report from Jeremy Drake and a fix idea from Andrew Dunstan.
1 parent f4a3e67 commit 31c341a

File tree

3 files changed

+31
-1
lines changed

3 files changed

+31
-1
lines changed

src/backend/libpq/pqcomm.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -481,6 +481,14 @@ static int
481481
Lock_AF_UNIX(unsigned short portNumber, char *unixSocketName)
482482
{
483483
UNIXSOCK_PATH(sock_path, portNumber, unixSocketName);
484+
if (strlen(sock_path) >= UNIXSOCK_PATH_BUFLEN)
485+
{
486+
ereport(LOG,
487+
(errmsg("Unix-domain socket path \"%s\" is too long (maximum %d bytes)",
488+
sock_path,
489+
(int) (UNIXSOCK_PATH_BUFLEN - 1))));
490+
return STATUS_ERROR;
491+
}
484492

485493
/*
486494
* Grab an interlock file associated with the socket file.

src/include/libpq/pqcomm.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,19 @@ typedef struct
7373
DEFAULT_PGSOCKET_DIR, \
7474
(port))
7575

76+
/*
77+
* The maximum workable length of a socket path is what will fit into
78+
* struct sockaddr_un. This is usually only 100 or so bytes :-(.
79+
*
80+
* For consistency, always pass a MAXPGPATH-sized buffer to UNIXSOCK_PATH(),
81+
* then complain if the resulting string is >= UNIXSOCK_PATH_BUFLEN bytes.
82+
* (Because the standard API for getaddrinfo doesn't allow it to complain in
83+
* a useful way when the socket pathname is too long, we have to test for
84+
* this explicitly, instead of just letting the subroutine return an error.)
85+
*/
86+
#define UNIXSOCK_PATH_BUFLEN sizeof(((struct sockaddr_un *) NULL)->sun_path)
87+
88+
7689
/*
7790
* These manipulate the frontend/backend protocol version number.
7891
*

src/interfaces/libpq/fe-connect.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1154,7 +1154,7 @@ static int
11541154
connectDBStart(PGconn *conn)
11551155
{
11561156
int portnum;
1157-
char portstr[128];
1157+
char portstr[MAXPGPATH];
11581158
struct addrinfo *addrs = NULL;
11591159
struct addrinfo hint;
11601160
const char *node;
@@ -1215,6 +1215,15 @@ connectDBStart(PGconn *conn)
12151215
node = NULL;
12161216
hint.ai_family = AF_UNIX;
12171217
UNIXSOCK_PATH(portstr, portnum, conn->pgunixsocket);
1218+
if (strlen(portstr) >= UNIXSOCK_PATH_BUFLEN)
1219+
{
1220+
appendPQExpBuffer(&conn->errorMessage,
1221+
libpq_gettext("Unix-domain socket path \"%s\" is too long (maximum %d bytes)\n"),
1222+
portstr,
1223+
(int) (UNIXSOCK_PATH_BUFLEN - 1));
1224+
conn->options_valid = false;
1225+
goto connect_errReturn;
1226+
}
12181227
#else
12191228
/* Without Unix sockets, default to localhost instead */
12201229
node = "localhost";

0 commit comments

Comments
 (0)