Damjan Jovanovic : ws2_32: getsockname should fail on unbound socket.

Alexandre Julliard julliard at wine.codeweavers.com
Fri Jun 15 07:23:04 CDT 2007


Module: wine
Branch: master
Commit: 1cf9436efe47b858a4cae33c956a78b8bcf83fbf
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=1cf9436efe47b858a4cae33c956a78b8bcf83fbf

Author: Damjan Jovanovic <damjan.jov at gmail.com>
Date:   Thu Jun 14 15:27:29 2007 +0200

ws2_32: getsockname should fail on unbound socket.

---

 dlls/ws2_32/socket.c     |   33 +++++++++++++++++++++++++++++++++
 dlls/ws2_32/tests/sock.c |   10 ++++++++++
 2 files changed, 43 insertions(+), 0 deletions(-)

diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c
index 456be21..aab3888 100644
--- a/dlls/ws2_32/socket.c
+++ b/dlls/ws2_32/socket.c
@@ -927,6 +927,35 @@ static unsigned int ws_sockaddr_ws2u(const struct WS_sockaddr* wsaddr, int wsadd
     return uaddrlen;
 }
 
+static BOOL is_sockaddr_bound(const struct sockaddr *uaddr, int uaddrlen)
+{
+    switch (uaddr->sa_family)
+    {
+#ifdef HAVE_IPX
+        case AF_IPX:
+            FIXME("don't know how to tell if IPX socket is bound, assuming it is!\n");
+            return TRUE;
+#endif
+        case AF_INET6:
+        {
+            static const struct sockaddr_in6 emptyAddr;
+            const struct sockaddr_in6 *in6 = (const struct sockaddr_in6*) uaddr;
+            return in6->sin6_port || memcmp(&in6->sin6_addr, &emptyAddr.sin6_addr, sizeof(struct in6_addr));
+        }
+        case AF_INET:
+        {
+            static const struct sockaddr_in emptyAddr;
+            const struct sockaddr_in *in = (const struct sockaddr_in*) uaddr;
+            return in->sin_port || memcmp(&in->sin_addr, &emptyAddr.sin_addr, sizeof(struct in_addr));
+        }
+        case AF_UNSPEC:
+            return FALSE;
+        default:
+            FIXME("unknown address family %d\n", uaddr->sa_family);
+            return TRUE;
+    }
+}
+
 /* Returns 0 if successful, -1 if the buffer is too small */
 static int ws_sockaddr_u2ws(const struct sockaddr* uaddr, struct WS_sockaddr* wsaddr, int* wsaddrlen)
 {
@@ -1590,6 +1619,10 @@ int WINAPI WS_getsockname(SOCKET s, struct WS_sockaddr *name, int *namelen)
         {
             SetLastError(wsaErrno());
         }
+        else if (!is_sockaddr_bound(&uaddr.addr, uaddrlen))
+        {
+            SetLastError(WSAEINVAL);
+        }
         else if (ws_sockaddr_u2ws(&uaddr.addr, name, namelen) != 0)
         {
             /* The buffer was too small */
diff --git a/dlls/ws2_32/tests/sock.c b/dlls/ws2_32/tests/sock.c
index 3403715..cc41320 100644
--- a/dlls/ws2_32/tests/sock.c
+++ b/dlls/ws2_32/tests/sock.c
@@ -1644,6 +1644,16 @@ static void test_getsockname(void)
         return;
     }
 
+    memcpy(&sa_get, &sa_set, sizeof(sa_set));
+    if (getsockname(sock, (struct sockaddr*) &sa_get, &sa_get_len) == 0)
+        ok(0, "getsockname on unbound socket should fail\n");
+    else {
+        ok(WSAGetLastError() == WSAEINVAL, "getsockname on unbound socket "
+            "failed with %d, expected %d\n", WSAGetLastError(), WSAEINVAL);
+        ok(memcmp(&sa_get, &sa_set, sizeof(sa_get)) == 0,
+            "failed getsockname modified sockaddr when it shouldn't\n");
+    }
+
     if(bind(sock, (struct sockaddr *) &sa_set, sa_set_len) < 0){
         trace("Failed to bind socket: %d\n", WSAGetLastError());
         closesocket(sock);




More information about the wine-cvs mailing list