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

This commit is contained in:
Hans Leidekker 2013-10-02 16:06:25 +02:00 committed by Alexandre Julliard
parent 9530a06fed
commit 260119e682
2 changed files with 150 additions and 34 deletions

View File

@ -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)

View File

@ -3110,55 +3110,94 @@ 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;
}
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());
}
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)
{
trace("error making server socket listen: %d\n", WSAGetLastError());
closesocket(server_socket);
return INVALID_SOCKET;
}
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 %d\n", WSAGetLastError());
ret = connect(connector, (struct sockaddr *)addr, len);
ok(!ret, "connecting to accepting socket failed %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;
ret = bind(server_socket, (struct sockaddr*) &address, sizeof(address));
if (ret != 0)
{
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;
server_socket = setup_server_socket(&address, &socklen);
if (server_socket == INVALID_SOCKET)
{
trace("error creating server socket: %d\n", WSAGetLastError());
return;
}
ret = listen(server_socket, 5);
if (ret != 0)
{
trace("error making server socket listen: %d\n", WSAGetLastError());
goto done;
}
connector = setup_connector_socket(&address, socklen);
if (connector == INVALID_SOCKET) goto done;
trace("Blocking accept next\n");
connector = socket(AF_INET, SOCK_STREAM, 0);
ok(connector != INVALID_SOCKET, "Failed to create connector socket, error %d\n", WSAGetLastError());
ret = connect(connector, (struct sockaddr*)&address, sizeof(address));
ok(ret == 0, "connecting to accepting socket failed, error %d\n", WSAGetLastError());
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);