Skip to content

Commit a8e60f0

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 edfc84b commit a8e60f0

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
@@ -493,6 +493,14 @@ static int
493493
Lock_AF_UNIX(unsigned short portNumber, char *unixSocketName)
494494
{
495495
UNIXSOCK_PATH(sock_path, portNumber, unixSocketName);
496+
if (strlen(sock_path) >= UNIXSOCK_PATH_BUFLEN)
497+
{
498+
ereport(LOG,
499+
(errmsg("Unix-domain socket path \"%s\" is too long (maximum %d bytes)",
500+
sock_path,
501+
(int) (UNIXSOCK_PATH_BUFLEN - 1))));
502+
return STATUS_ERROR;
503+
}
496504

497505
/*
498506
* 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
@@ -1300,7 +1300,7 @@ static int
13001300
connectDBStart(PGconn *conn)
13011301
{
13021302
int portnum;
1303-
char portstr[128];
1303+
char portstr[MAXPGPATH];
13041304
struct addrinfo *addrs = NULL;
13051305
struct addrinfo hint;
13061306
const char *node;
@@ -1362,6 +1362,15 @@ connectDBStart(PGconn *conn)
13621362
node = NULL;
13631363
hint.ai_family = AF_UNIX;
13641364
UNIXSOCK_PATH(portstr, portnum, conn->pgunixsocket);
1365+
if (strlen(portstr) >= UNIXSOCK_PATH_BUFLEN)
1366+
{
1367+
appendPQExpBuffer(&conn->errorMessage,
1368+
libpq_gettext("Unix-domain socket path \"%s\" is too long (maximum %d bytes)\n"),
1369+
portstr,
1370+
(int) (UNIXSOCK_PATH_BUFLEN - 1));
1371+
conn->options_valid = false;
1372+
goto connect_errReturn;
1373+
}
13651374
#else
13661375
/* Without Unix sockets, default to localhost instead */
13671376
node = DefaultHost;

0 commit comments

Comments
 (0)