Alexandre Julliard : ws2_32: Fail when select is called with an invalid fd.
Alexandre Julliard
julliard at winehq.org
Tue Oct 5 14:41:48 CDT 2010
Module: wine
Branch: stable
Commit: 16f8f424d9626fda167fc4260365ebfe887e2ca5
URL: http://source.winehq.org/git/wine.git/?a=commit;h=16f8f424d9626fda167fc4260365ebfe887e2ca5
Author: Alexandre Julliard <julliard at winehq.org>
Date: Thu Sep 30 20:32:43 2010 +0200
ws2_32: Fail when select is called with an invalid fd.
Based on a patch by Vincent Povirk.
(cherry picked from commit 4cbfe4e1efb8c372cc95d91b3572f56e20e2e64c)
---
dlls/ws2_32/socket.c | 27 +++++++++++++++++++++++----
dlls/ws2_32/tests/sock.c | 26 ++++++++++++++++++++++++++
2 files changed, 49 insertions(+), 4 deletions(-)
diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c
index 4191f80..0233af1 100644
--- a/dlls/ws2_32/socket.c
+++ b/dlls/ws2_32/socket.c
@@ -2958,11 +2958,16 @@ static struct pollfd *fd_sets_to_poll( const WS_fd_set *readfds, const WS_fd_set
if (exceptfds) count += exceptfds->fd_count;
*count_ptr = count;
if (!count) return NULL;
- if (!(fds = HeapAlloc( GetProcessHeap(), 0, count * sizeof(fds[0])))) return NULL;
+ if (!(fds = HeapAlloc( GetProcessHeap(), 0, count * sizeof(fds[0]))))
+ {
+ SetLastError( ERROR_NOT_ENOUGH_MEMORY );
+ return NULL;
+ }
if (readfds)
for (i = 0; i < readfds->fd_count; i++, j++)
{
fds[j].fd = get_sock_fd( readfds->fd_array[i], FILE_READ_DATA, NULL );
+ if (fds[j].fd == -1) goto failed;
fds[j].events = POLLIN;
fds[j].revents = 0;
}
@@ -2970,6 +2975,7 @@ static struct pollfd *fd_sets_to_poll( const WS_fd_set *readfds, const WS_fd_set
for (i = 0; i < writefds->fd_count; i++, j++)
{
fds[j].fd = get_sock_fd( writefds->fd_array[i], FILE_WRITE_DATA, NULL );
+ if (fds[j].fd == -1) goto failed;
fds[j].events = POLLOUT;
fds[j].revents = 0;
}
@@ -2977,10 +2983,26 @@ static struct pollfd *fd_sets_to_poll( const WS_fd_set *readfds, const WS_fd_set
for (i = 0; i < exceptfds->fd_count; i++, j++)
{
fds[j].fd = get_sock_fd( exceptfds->fd_array[i], 0, NULL );
+ if (fds[j].fd == -1) goto failed;
fds[j].events = POLLHUP;
fds[j].revents = 0;
}
return fds;
+
+failed:
+ count = j;
+ j = 0;
+ if (readfds)
+ for (i = 0; i < readfds->fd_count && j < count; i++, j++)
+ release_sock_fd( readfds->fd_array[i], fds[j].fd );
+ if (writefds)
+ for (i = 0; i < writefds->fd_count && j < count; i++, j++)
+ release_sock_fd( writefds->fd_array[i], fds[j].fd );
+ if (exceptfds)
+ for (i = 0; i < exceptfds->fd_count && j < count; i++, j++)
+ release_sock_fd( exceptfds->fd_array[i], fds[j].fd );
+ HeapFree( GetProcessHeap(), 0, fds );
+ return NULL;
}
/* release the file descriptor obtained in fd_sets_to_poll */
@@ -3059,10 +3081,7 @@ int WINAPI WS_select(int nfds, WS_fd_set *ws_readfds,
ws_readfds, ws_writefds, ws_exceptfds, ws_timeout);
if (!(pollfds = fd_sets_to_poll( ws_readfds, ws_writefds, ws_exceptfds, &count )) && count)
- {
- SetLastError( ERROR_NOT_ENOUGH_MEMORY );
return SOCKET_ERROR;
- }
if (ws_timeout)
{
diff --git a/dlls/ws2_32/tests/sock.c b/dlls/ws2_32/tests/sock.c
index 9217913..8d7c7a6 100644
--- a/dlls/ws2_32/tests/sock.c
+++ b/dlls/ws2_32/tests/sock.c
@@ -1937,6 +1937,32 @@ static void test_select(void)
broken(thread_params.ReadKilled == 0), /*Win98*/
"closesocket did not wakeup select\n");
+ /* Test selecting invalid handles */
+ FD_ZERO(&readfds);
+ FD_ZERO(&writefds);
+ FD_ZERO(&exceptfds);
+ FD_SET(INVALID_SOCKET, &readfds);
+ SetLastError(0);
+ ret = select(maxfd+1, &readfds, &writefds, &exceptfds, &select_timeout);
+ ok ( (ret == SOCKET_ERROR), "expected SOCKET_ERROR, got %i\n", ret);
+ ok ( GetLastError() == WSAENOTSOCK, "expected WSAENOTSOCK, got %i\n", ret);
+ ok ( !FD_ISSET(fdRead, &readfds), "FD should not be set\n");
+
+ FD_ZERO(&readfds);
+ FD_SET(INVALID_SOCKET, &writefds);
+ SetLastError(0);
+ ret = select(maxfd+1, &readfds, &writefds, &exceptfds, &select_timeout);
+ ok ( (ret == SOCKET_ERROR), "expected SOCKET_ERROR, got %i\n", ret);
+ ok ( GetLastError() == WSAENOTSOCK, "expected WSAENOTSOCK, got %i\n", ret);
+ ok ( !FD_ISSET(fdRead, &writefds), "FD should not be set\n");
+
+ FD_ZERO(&writefds);
+ FD_SET(INVALID_SOCKET, &exceptfds);
+ SetLastError(0);
+ ret = select(maxfd+1, &readfds, &writefds, &exceptfds, &select_timeout);
+ ok ( (ret == SOCKET_ERROR), "expected SOCKET_ERROR, got %i\n", ret);
+ ok ( GetLastError() == WSAENOTSOCK, "expected WSAENOTSOCK, got %i\n", ret);
+ ok ( !FD_ISSET(fdRead, &exceptfds), "FD should not be set\n");
}
static DWORD WINAPI AcceptKillThread(select_thread_params *par)
More information about the wine-cvs
mailing list