]> granicus.if.org Git - postgresql/commitdiff
check socket creation errors against PGINVALID_SOCKET
authorBruce Momjian <bruce@momjian.us>
Wed, 16 Apr 2014 14:45:48 +0000 (10:45 -0400)
committerBruce Momjian <bruce@momjian.us>
Wed, 16 Apr 2014 14:45:48 +0000 (10:45 -0400)
Previously, in some places, socket creation errors were checked for
negative values, which is not true for Windows because sockets are
unsigned.  This masked socket creation errors on Windows.

Backpatch through 9.0.  8.4 doesn't have the infrastructure to fix this.

src/backend/libpq/auth.c
src/backend/libpq/ip.c
src/backend/libpq/pqcomm.c
src/backend/port/win32/socket.c
src/backend/postmaster/postmaster.c
src/interfaces/libpq/fe-connect.c
src/interfaces/libpq/libpq-int.h

index d062c1d8cef91b6bb4279ff1541348923e6acdd5..8fa9aa797f42fab8f3b46399f0005faa7b34aba4 100644 (file)
@@ -1463,7 +1463,7 @@ ident_inet(hbaPort *port)
 
        sock_fd = socket(ident_serv->ai_family, ident_serv->ai_socktype,
                                         ident_serv->ai_protocol);
-       if (sock_fd < 0)
+       if (sock_fd == PGINVALID_SOCKET)
        {
                ereport(LOG,
                                (errcode_for_socket_access(),
@@ -1543,7 +1543,7 @@ ident_inet(hbaPort *port)
                                        ident_response)));
 
 ident_inet_done:
-       if (sock_fd >= 0)
+       if (sock_fd != PGINVALID_SOCKET)
                closesocket(sock_fd);
        pg_freeaddrinfo_all(remote_addr.addr.ss_family, ident_serv);
        pg_freeaddrinfo_all(local_addr.addr.ss_family, la);
@@ -2361,7 +2361,7 @@ CheckRADIUSAuth(Port *port)
        packet->length = htons(packet->length);
 
        sock = socket(serveraddrs[0].ai_family, SOCK_DGRAM, 0);
-       if (sock < 0)
+       if (sock == PGINVALID_SOCKET)
        {
                ereport(LOG,
                                (errmsg("could not create RADIUS socket: %m")));
index 7e8fc785bb415081d8e8c89bfd0850d463c58179..acdbab0049635af25ded884757f9fcc71f93019e 100644 (file)
@@ -547,7 +547,7 @@ pg_foreach_ifaddr(PgIfAddrCallback callback, void *cb_data)
        int                     error;
 
        sock = WSASocket(AF_INET, SOCK_DGRAM, 0, 0, 0, 0);
-       if (sock == SOCKET_ERROR)
+       if (sock == INVALID_SOCKET)
                return -1;
 
        while (n_ii < 1024)
@@ -670,7 +670,7 @@ pg_foreach_ifaddr(PgIfAddrCallback callback, void *cb_data)
                                total;
 
        sock = socket(AF_INET, SOCK_DGRAM, 0);
-       if (sock == -1)
+       if (sock == PGINVALID_SOCKET)
                return -1;
 
        while (n_buffer < 1024 * 100)
@@ -711,7 +711,7 @@ pg_foreach_ifaddr(PgIfAddrCallback callback, void *cb_data)
 #ifdef HAVE_IPV6
        /* We'll need an IPv6 socket too for the SIOCGLIFNETMASK ioctls */
        sock6 = socket(AF_INET6, SOCK_DGRAM, 0);
-       if (sock6 == -1)
+       if (sock6 == PGINVALID_SOCKET)
        {
                free(buffer);
                close(sock);
@@ -788,10 +788,10 @@ pg_foreach_ifaddr(PgIfAddrCallback callback, void *cb_data)
        char       *ptr,
                           *buffer = NULL;
        size_t          n_buffer = 1024;
-       int                     sock;
+       pgsocket        sock;
 
        sock = socket(AF_INET, SOCK_DGRAM, 0);
-       if (sock == -1)
+       if (sock == PGINVALID_SOCKET)
                return -1;
 
        while (n_buffer < 1024 * 100)
index 1eae183e33a71ecca141e1b1563b4d7b4a5c0a0b..0179451f080947882b2dc6537e07dc9796eab178 100644 (file)
@@ -392,7 +392,7 @@ StreamServerPort(int family, char *hostName, unsigned short portNumber,
                                break;
                }
 
-               if ((fd = socket(addr->ai_family, SOCK_STREAM, 0)) < 0)
+               if ((fd = socket(addr->ai_family, SOCK_STREAM, 0)) == PGINVALID_SOCKET)
                {
                        ereport(LOG,
                                        (errcode_for_socket_access(),
@@ -632,7 +632,7 @@ StreamConnection(pgsocket server_fd, Port *port)
        port->raddr.salen = sizeof(port->raddr.addr);
        if ((port->sock = accept(server_fd,
                                                         (struct sockaddr *) & port->raddr.addr,
-                                                        &port->raddr.salen)) < 0)
+                                                        &port->raddr.salen)) == PGINVALID_SOCKET)
        {
                ereport(LOG,
                                (errcode_for_socket_access(),
index 4f1099f6cf889945b44d10d3f0d87d4b5ec50a1d..adc0e02335f3f64b88995577b1c145ae99259d95 100644 (file)
@@ -132,7 +132,7 @@ int
 pgwin32_waitforsinglesocket(SOCKET s, int what, int timeout)
 {
        static HANDLE waitevent = INVALID_HANDLE_VALUE;
-       static SOCKET current_socket = -1;
+       static SOCKET current_socket = INVALID_SOCKET;
        static int      isUDP = 0;
        HANDLE          events[2];
        int                     r;
index bb771a63f2d7c9c8b0c8d4e2282283df7bf8e63b..b573fd82b6317726aef3989379f933b8e5097835 100644 (file)
@@ -2169,7 +2169,7 @@ ConnCreate(int serverFd)
 
        if (StreamConnection(serverFd, port) != STATUS_OK)
        {
-               if (port->sock >= 0)
+               if (port->sock != PGINVALID_SOCKET)
                        StreamClose(port->sock);
                ConnFree(port);
                return NULL;
index d53c41f6a3d742a66908f400b44539fc1595ae78..51d4de419b4536cb7ab8d3a492667c4138418d31 100644 (file)
@@ -1632,8 +1632,23 @@ keep_going:                                              /* We will come back to here until there is
                                        conn->raddr.salen = addr_cur->ai_addrlen;
 
                                        /* Open a socket */
-                                       conn->sock = socket(addr_cur->ai_family, SOCK_STREAM, 0);
-                                       if (conn->sock < 0)
+                                       {
+                                               /*
+                                                * While we use 'pgsocket' as the socket type in the
+                                                * backend, we use 'int' for libpq socket values.
+                                                * This requires us to map PGINVALID_SOCKET to -1
+                                                * on Windows.
+                                                * See http://msdn.microsoft.com/en-us/library/windows/desktop/ms740516%28v=vs.85%29.aspx
+                                                */
+                                               pgsocket sock = socket(addr_cur->ai_family, SOCK_STREAM, 0);
+#ifdef WIN32
+                                               if (sock == PGINVALID_SOCKET)
+                                                       conn->sock = -1;
+                                               else
+#endif
+                                                       conn->sock = sock;
+                                       }
+                                       if (conn->sock == -1)
                                        {
                                                /*
                                                 * ignore socket() failure if we have more addresses
@@ -3136,7 +3151,7 @@ internal_cancel(SockAddr *raddr, int be_pid, int be_key,
                                char *errbuf, int errbufsize)
 {
        int                     save_errno = SOCK_ERRNO;
-       int                     tmpsock = -1;
+       pgsocket        tmpsock = PGINVALID_SOCKET;
        char            sebuf[256];
        int                     maxlen;
        struct
@@ -3149,7 +3164,7 @@ internal_cancel(SockAddr *raddr, int be_pid, int be_key,
         * We need to open a temporary connection to the postmaster. Do this with
         * only kernel calls.
         */
-       if ((tmpsock = socket(raddr->addr.ss_family, SOCK_STREAM, 0)) < 0)
+       if ((tmpsock = socket(raddr->addr.ss_family, SOCK_STREAM, 0)) == PGINVALID_SOCKET)
        {
                strlcpy(errbuf, "PQcancel() -- socket() failed: ", errbufsize);
                goto cancel_errReturn;
@@ -3220,7 +3235,7 @@ cancel_errReturn:
                                maxlen);
                strcat(errbuf, "\n");
        }
-       if (tmpsock >= 0)
+       if (tmpsock != PGINVALID_SOCKET)
                closesocket(tmpsock);
        SOCK_ERRNO_SET(save_errno);
        return FALSE;
@@ -5300,6 +5315,15 @@ PQerrorMessage(const PGconn *conn)
        return conn->errorMessage.data;
 }
 
+/*
+ * In Windows, socket values are unsigned, and an invalid socket value
+ * (INVALID_SOCKET) is ~0, which equals -1 in comparisons (with no compiler
+ * warning). Ideally we would return an unsigned value for PQsocket() on
+ * Windows, but that would cause the function's return value to differ from
+ * Unix, so we just return -1 for invalid sockets.
+ * http://msdn.microsoft.com/en-us/library/windows/desktop/cc507522%28v=vs.85%29.aspx
+ * http://stackoverflow.com/questions/10817252/why-is-invalid-socket-defined-as-0-in-winsock2-h-c
+ */
 int
 PQsocket(const PGconn *conn)
 {
index 22bbe4a48ebea99e685acc0ac4485f2d81645f17..ee975d41fa1c94690e60c5fdec87f84b81dc7e3c 100644 (file)
@@ -364,6 +364,7 @@ struct pg_conn
        PGnotify   *notifyTail;         /* newest unreported Notify msg */
 
        /* Connection data */
+       /* See PQconnectPoll() for how we use 'int' and not 'pgsocket'. */
        int                     sock;                   /* Unix FD for socket, -1 if not connected */
        SockAddr        laddr;                  /* Local address */
        SockAddr        raddr;                  /* Remote address */