Module: wine Branch: master Commit: 260119e682d484df48bca9e2ec8ad9ccd9e3b8ff URL: http://source.winehq.org/git/wine.git/?a=commit;h=260119e682d484df48bca9e2ec...
Author: Hans Leidekker hans@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);