]> 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 c749139eed60eea39143b9eb723877801e6aa555..25d0e215d0152337a8b4a9813dd5f6d7cb0b0fc9 100644 (file)
@@ -1664,7 +1664,7 @@ ident_inet(const SockAddr remote_addr,
 
        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(),
@@ -1744,7 +1744,7 @@ ident_inet(const SockAddr remote_addr,
                                        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);
@@ -2750,7 +2750,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 c6c264e4b0c123ceb3e39a5d6029ccf602741b3a..0491d16643a7bf211d9629fa39e9a163bd2604e2 100644 (file)
@@ -552,7 +552,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)
@@ -675,7 +675,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)
@@ -716,7 +716,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);
@@ -793,10 +793,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 e93090602f3506e164e695318b4432aeac1e2ea3..d7302d822e355d4542e5ac3e78297b078cc3dbaf 100644 (file)
@@ -351,7 +351,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(),
@@ -594,7 +594,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 6c7d327c6fb66ce12402c0f0f401478e12ddffc3..d0d4aac3c264bf265fd04da5eef1aa6617b7d9ee 100644 (file)
@@ -131,7 +131,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 1f6de1671231160c74e3e9ff8acc63c0d3ceafe5..4f5e3522fe530baa68a3e7642ad9b228885864cf 100644 (file)
@@ -1982,7 +1982,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 02ef3dc7b35f5ac35dfeb02bb79620fc312e2c8f..85da0a009af50dc35a7e16c69ec401e8af8e200c 100644 (file)
@@ -1480,8 +1480,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
@@ -2892,7 +2907,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
@@ -2905,7 +2920,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;
@@ -2976,7 +2991,7 @@ cancel_errReturn:
                                maxlen);
                strcat(errbuf, "\n");
        }
-       if (tmpsock >= 0)
+       if (tmpsock != PGINVALID_SOCKET)
                closesocket(tmpsock);
        SOCK_ERRNO_SET(save_errno);
        return FALSE;
@@ -4389,6 +4404,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 3cfe5ecd1bf8a4b11a9cc1111676eba502a9376d..e873750f2a6a21fefb9a244994d086fa60ecface 100644 (file)
@@ -342,6 +342,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 */