From 425b30bc7898f4fe8a65a5481bb5994eccdb59be Mon Sep 17 00:00:00 2001 From: usa Date: Fri, 13 May 2011 06:24:36 +0000 Subject: * win32/win32.c (rb_w32_select): check invalid handle before doing select operations. see [ruby-dev:43513], [ruby-dev:43535] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@31543 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- win32/win32.c | 64 +++++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 43 insertions(+), 21 deletions(-) (limited to 'win32/win32.c') diff --git a/win32/win32.c b/win32/win32.c index 08d123ee57..6d04caa649 100644 --- a/win32/win32.c +++ b/win32/win32.c @@ -2391,34 +2391,41 @@ static int extract_fd(rb_fdset_t *dst, fd_set *src, int (*func)(SOCKET)) { unsigned int s = 0; - if (!src || !dst) return 0; + unsigned int m = 0; + if (!src) return 0; while (s < src->fd_count) { SOCKET fd = src->fd_array[s]; - if (!func || (*func)(fd)) { /* move it to dst */ - unsigned int d; + if (!func || (*func)(fd)) { + if (dst) { /* move it to dst */ + unsigned int d; - for (d = 0; d < dst->fdset->fd_count; d++) { - if (dst->fdset->fd_array[d] == fd) - break; - } - if (d == dst->fdset->fd_count) { - if ((int)dst->fdset->fd_count >= dst->capa) { - dst->capa = (dst->fdset->fd_count / FD_SETSIZE + 1) * FD_SETSIZE; - dst->fdset = xrealloc(dst->fdset, sizeof(unsigned int) + sizeof(SOCKET) * dst->capa); + for (d = 0; d < dst->fdset->fd_count; d++) { + if (dst->fdset->fd_array[d] == fd) + break; + } + if (d == dst->fdset->fd_count) { + if ((int)dst->fdset->fd_count >= dst->capa) { + dst->capa = (dst->fdset->fd_count / FD_SETSIZE + 1) * FD_SETSIZE; + dst->fdset = xrealloc(dst->fdset, sizeof(unsigned int) + sizeof(SOCKET) * dst->capa); + } + dst->fdset->fd_array[dst->fdset->fd_count++] = fd; } - dst->fdset->fd_array[dst->fdset->fd_count++] = fd; + memmove( + &src->fd_array[s], + &src->fd_array[s+1], + sizeof(src->fd_array[0]) * (--src->fd_count - s)); + } + else { + m++; + s++; } - memmove( - &src->fd_array[s], - &src->fd_array[s+1], - sizeof(src->fd_array[0]) * (--src->fd_count - s)); } else s++; } - return dst->fdset->fd_count; + return dst ? dst->fdset->fd_count : m; } static int @@ -2514,6 +2521,12 @@ is_readable_console(SOCKET sock) /* call this for console only */ return ret; } +static int +is_invalid_handle(SOCKET sock) +{ + return (HANDLE)sock == INVALID_HANDLE_VALUE; +} + static int do_select(int nfds, fd_set *rd, fd_set *wr, fd_set *ex, struct timeval *timeout) @@ -2625,15 +2638,24 @@ rb_w32_select(int nfds, fd_set *rd, fd_set *wr, fd_set *ex, rb_fd_init(&else_rd); nonsock += extract_fd(&else_rd, rd, is_not_socket); + rb_fd_init(&else_wr); + nonsock += extract_fd(&else_wr, wr, is_not_socket); + + // check invalid handles + if (extract_fd(NULL, else_rd.fdset, is_invalid_handle) > 0 || + extract_fd(NULL, else_wr.fdset, is_invalid_handle) > 0) { + rb_fd_term(&else_wr); + rb_fd_term(&else_rd); + errno = EBADF; + return -1; + } + rb_fd_init(&pipe_rd); extract_fd(&pipe_rd, else_rd.fdset, is_pipe); // should not call is_pipe for socket rb_fd_init(&cons_rd); extract_fd(&cons_rd, else_rd.fdset, is_console); // ditto - rb_fd_init(&else_wr); - nonsock += extract_fd(&else_wr, wr, is_not_socket); - rb_fd_init(&except); extract_fd(&except, ex, is_not_socket); // drop only @@ -2694,9 +2716,9 @@ rb_w32_select(int nfds, fd_set *rd, fd_set *wr, fd_set *ex, } rb_fd_term(&except); - rb_fd_term(&else_wr); rb_fd_term(&cons_rd); rb_fd_term(&pipe_rd); + rb_fd_term(&else_wr); rb_fd_term(&else_rd); return r; -- cgit v1.2.3