Alexandre Julliard : ws2_32: Fail when select is called with an invalid fd.

Alexandre Julliard julliard at winehq.org
Mon Sep 20 12:12:23 CDT 2010


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

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Mon Sep 20 14:56:55 2010 +0200

ws2_32: Fail when select is called with an invalid fd.

Based on a patch by Vincent Povirk.

---

 dlls/ws2_32/socket.c     |   27 +++++++++++++++++++++++----
 dlls/ws2_32/tests/sock.c |    6 +++---
 2 files changed, 26 insertions(+), 7 deletions(-)

diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c
index 0335d41..1894772 100644
--- a/dlls/ws2_32/socket.c
+++ b/dlls/ws2_32/socket.c
@@ -3087,11 +3087,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;
         }
@@ -3099,6 +3104,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;
         }
@@ -3106,10 +3112,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 */
@@ -3188,10 +3210,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 16c6fcb..b2a22af 100644
--- a/dlls/ws2_32/tests/sock.c
+++ b/dlls/ws2_32/tests/sock.c
@@ -1946,7 +1946,7 @@ static void test_select(void)
     FD_SET(INVALID_SOCKET, &readfds);
     SetLastError(0);
     ret = select(maxfd+1, &readfds, &writefds, &exceptfds, &select_timeout);
-    todo_wine ok ( (ret == SOCKET_ERROR), "expected SOCKET_ERROR, got %i\n", ret);
+    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");
 
@@ -1954,7 +1954,7 @@ static void test_select(void)
     FD_SET(INVALID_SOCKET, &writefds);
     SetLastError(0);
     ret = select(maxfd+1, &readfds, &writefds, &exceptfds, &select_timeout);
-    todo_wine ok ( (ret == SOCKET_ERROR), "expected SOCKET_ERROR, got %i\n", ret);
+    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");
 
@@ -1962,7 +1962,7 @@ static void test_select(void)
     FD_SET(INVALID_SOCKET, &exceptfds);
     SetLastError(0);
     ret = select(maxfd+1, &readfds, &writefds, &exceptfds, &select_timeout);
-    todo_wine ok ( (ret == SOCKET_ERROR), "expected SOCKET_ERROR, got %i\n", ret);
+    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");
 }




More information about the wine-cvs mailing list