Hans Leidekker : ws2_32: Return an error from accept if the address buffer is too small.

Alexandre Julliard julliard at winehq.org
Wed Oct 2 15:49:13 CDT 2013


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

Author: Hans Leidekker <hans at codeweavers.com>
Date:   Wed Oct  2 16:06:25 2013 +0200

ws2_32: Return an error from accept if the address buffer is too small.

---

 dlls/ws2_32/socket.c     |    9 ++-
 dlls/ws2_32/tests/sock.c |  165 ++++++++++++++++++++++++++++++++++++++-------
 2 files changed, 145 insertions(+), 29 deletions(-)

diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c
index a14f624..1d2fbcb 100644
--- a/dlls/ws2_32/socket.c
+++ b/dlls/ws2_32/socket.c
@@ -2247,8 +2247,7 @@ static int WS2_register_async_shutdown( SOCKET s, int type )
 /***********************************************************************
  *		accept		(WS2_32.1)
  */
-SOCKET WINAPI WS_accept(SOCKET s, struct WS_sockaddr *addr,
-                                 int *addrlen32)
+SOCKET WINAPI WS_accept(SOCKET s, struct WS_sockaddr *addr, int *addrlen32)
 {
     NTSTATUS status;
     SOCKET as;
@@ -2275,7 +2274,11 @@ SOCKET WINAPI WS_accept(SOCKET s, struct WS_sockaddr *addr,
         SERVER_END_REQ;
         if (!status)
         {
-            if (addr) WS_getpeername(as, addr, addrlen32);
+            if (addr && WS_getpeername(as, addr, addrlen32))
+            {
+                WS_closesocket(as);
+                return SOCKET_ERROR;
+            }
             return as;
         }
         if (is_blocking && status == STATUS_CANT_WAIT)
diff --git a/dlls/ws2_32/tests/sock.c b/dlls/ws2_32/tests/sock.c
index 9fd8b58..2cf851f 100644
--- a/dlls/ws2_32/tests/sock.c
+++ b/dlls/ws2_32/tests/sock.c
@@ -3110,54 +3110,93 @@ static int CALLBACK AlwaysDeferConditionFunc(LPWSABUF lpCallerId, LPWSABUF lpCal
     return CF_DEFER;
 }
 
-static void test_accept(void)
+static SOCKET setup_server_socket(struct sockaddr_in *addr, int *len)
 {
-    int ret;
-    SOCKET server_socket = INVALID_SOCKET, accepted = INVALID_SOCKET, connector = INVALID_SOCKET;
-    struct sockaddr_in address;
-    int socklen;
-    select_thread_params thread_params;
-    HANDLE thread_handle = NULL;
-    DWORD id;
+    int ret, val;
+    SOCKET server_socket;
 
     server_socket = socket(AF_INET, SOCK_STREAM, 0);
     if (server_socket == INVALID_SOCKET)
     {
         trace("error creating server socket: %d\n", WSAGetLastError());
-        goto done;
+        return INVALID_SOCKET;
     }
 
-    memset(&address, 0, sizeof(address));
-    address.sin_addr.s_addr = inet_addr("127.0.0.1");
-    address.sin_family = AF_INET;
-    ret = bind(server_socket, (struct sockaddr*) &address, sizeof(address));
-    if (ret != 0)
+    val = 1;
+    ret = setsockopt(server_socket, SOL_SOCKET, SO_REUSEADDR, (char *)&val, sizeof(val));
+    if (ret)
+    {
+        trace("error setting SO_REUSEADDR: %d\n", WSAGetLastError());
+        closesocket(server_socket);
+        return INVALID_SOCKET;
+    }
+
+    ret = bind(server_socket, (struct sockaddr *)addr, *len);
+    if (ret)
     {
         trace("error binding server socket: %d\n", WSAGetLastError());
-        goto done;
     }
 
-    socklen = sizeof(address);
-    ret = getsockname(server_socket, (struct sockaddr*)&address, &socklen);
-    if (ret != 0) {
-        skip("failed to lookup bind address, error %d\n", WSAGetLastError());
-        goto done;
+    ret = getsockname(server_socket, (struct sockaddr *)addr, len);
+    if (ret)
+    {
+        skip("failed to lookup bind address: %d\n", WSAGetLastError());
+        closesocket(server_socket);
+        return INVALID_SOCKET;
     }
 
     ret = listen(server_socket, 5);
-    if (ret != 0)
+    if (ret)
     {
         trace("error making server socket listen: %d\n", WSAGetLastError());
-        goto done;
+        closesocket(server_socket);
+        return INVALID_SOCKET;
     }
 
-    trace("Blocking accept next\n");
+    return server_socket;
+}
+
+static SOCKET setup_connector_socket(struct sockaddr_in *addr, int len)
+{
+    int ret;
+    SOCKET connector;
 
     connector = socket(AF_INET, SOCK_STREAM, 0);
-    ok(connector != INVALID_SOCKET, "Failed to create connector socket, error %d\n", WSAGetLastError());
+    ok(connector != INVALID_SOCKET, "failed to create connector socket %d\n", WSAGetLastError());
+
+    ret = connect(connector, (struct sockaddr *)addr, len);
+    ok(!ret, "connecting to accepting socket failed %d\n", WSAGetLastError());
 
-    ret = connect(connector, (struct sockaddr*)&address, sizeof(address));
-    ok(ret == 0, "connecting to accepting socket failed, error %d\n", WSAGetLastError());
+    return connector;
+}
+
+static void test_accept(void)
+{
+    int ret;
+    SOCKET server_socket, accepted = INVALID_SOCKET, connector;
+    struct sockaddr_in address;
+    SOCKADDR_STORAGE ss;
+    int socklen;
+    select_thread_params thread_params;
+    HANDLE thread_handle = NULL;
+    DWORD id;
+
+    memset(&address, 0, sizeof(address));
+    address.sin_addr.s_addr = inet_addr("127.0.0.1");
+    address.sin_family = AF_INET;
+
+    socklen = sizeof(address);
+    server_socket = setup_server_socket(&address, &socklen);
+    if (server_socket == INVALID_SOCKET)
+    {
+        trace("error creating server socket: %d\n", WSAGetLastError());
+        return;
+    }
+
+    connector = setup_connector_socket(&address, socklen);
+    if (connector == INVALID_SOCKET) goto done;
+
+    trace("Blocking accept next\n");
 
     accepted = WSAAccept(server_socket, NULL, NULL, AlwaysDeferConditionFunc, 0);
     ok(accepted == INVALID_SOCKET && WSAGetLastError() == WSATRY_AGAIN, "Failed to defer connection, %d\n", WSAGetLastError());
@@ -3194,6 +3233,80 @@ static void test_accept(void)
     ok(thread_params.ReadKilled || broken(!thread_params.ReadKilled) /* Win98/ME, after accept */,
        "closesocket did not wakeup accept\n");
 
+    closesocket(accepted);
+    closesocket(connector);
+    accepted = connector = server_socket = INVALID_SOCKET;
+
+    socklen = sizeof(address);
+    server_socket = setup_server_socket(&address, &socklen);
+    if (server_socket == INVALID_SOCKET) goto done;
+
+    connector = setup_connector_socket(&address, socklen);
+    if (connector == INVALID_SOCKET) goto done;
+
+    socklen = 0;
+    accepted = WSAAccept(server_socket, (struct sockaddr *)&ss, &socklen, NULL, 0);
+    todo_wine ok(accepted == INVALID_SOCKET && WSAGetLastError() == WSAEFAULT, "got %d\n", WSAGetLastError());
+    ok(!socklen, "got %d\n", socklen);
+    closesocket(connector);
+    connector = INVALID_SOCKET;
+
+    socklen = sizeof(address);
+    connector = setup_connector_socket(&address, socklen);
+    if (connector == INVALID_SOCKET) goto done;
+
+    accepted = WSAAccept(server_socket, NULL, NULL, NULL, 0);
+    ok(accepted != INVALID_SOCKET, "Failed to accept connection, %d\n", WSAGetLastError());
+    closesocket(accepted);
+    closesocket(connector);
+    accepted = connector = INVALID_SOCKET;
+
+    socklen = sizeof(address);
+    connector = setup_connector_socket(&address, socklen);
+    if (connector == INVALID_SOCKET) goto done;
+
+    socklen = sizeof(ss);
+    memset(&ss, 0, sizeof(ss));
+    accepted = WSAAccept(server_socket, (struct sockaddr *)&ss, &socklen, NULL, 0);
+    ok(accepted != INVALID_SOCKET, "Failed to accept connection, %d\n", WSAGetLastError());
+    todo_wine ok(socklen != sizeof(ss), "unexpected length\n");
+    todo_wine ok(ss.ss_family, "family not set\n");
+    closesocket(accepted);
+    closesocket(connector);
+    accepted = connector = INVALID_SOCKET;
+
+    socklen = sizeof(address);
+    connector = setup_connector_socket(&address, socklen);
+    if (connector == INVALID_SOCKET) goto done;
+
+    socklen = 0;
+    accepted = accept(server_socket, (struct sockaddr *)&ss, &socklen);
+    ok(accepted == INVALID_SOCKET && WSAGetLastError() == WSAEFAULT, "got %d\n", WSAGetLastError());
+    ok(!socklen, "got %d\n", socklen);
+    closesocket(connector);
+    accepted = connector = INVALID_SOCKET;
+
+    socklen = sizeof(address);
+    connector = setup_connector_socket(&address, socklen);
+    if (connector == INVALID_SOCKET) goto done;
+
+    accepted = accept(server_socket, NULL, NULL);
+    ok(accepted != INVALID_SOCKET, "Failed to accept connection, %d\n", WSAGetLastError());
+    closesocket(accepted);
+    closesocket(connector);
+    accepted = connector = INVALID_SOCKET;
+
+    socklen = sizeof(address);
+    connector = setup_connector_socket(&address, socklen);
+    if (connector == INVALID_SOCKET) goto done;
+
+    socklen = sizeof(ss);
+    memset(&ss, 0, sizeof(ss));
+    accepted = accept(server_socket, (struct sockaddr *)&ss, &socklen);
+    ok(accepted != INVALID_SOCKET, "Failed to accept connection, %d\n", WSAGetLastError());
+    ok(socklen != sizeof(ss), "unexpected length\n");
+    ok(ss.ss_family, "family not set\n");
+
 done:
     if (accepted != INVALID_SOCKET)
         closesocket(accepted);




More information about the wine-cvs mailing list