From 48d39345bc0f19e6ba39f40950018e1edd0cccb2 Mon Sep 17 00:00:00 2001 From: Bert Belder Date: Tue, 9 Dec 2014 22:53:05 +0100 Subject: [PATCH] win: avoid stack corruption when closing a poll handle MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When the user closes an uv_poll_t handle, there may still be an outstanding AFD_POLL request. Libuv can't cancel this AFD_POLL request directly, so it has to submit another which makes the the previous poll request return. Libuv completely forgets about the "canceling" AFD_POLL request, but at some point in time it may complete and store its result somewhere in memory. Without this patch the result of the canceling poll request is written somewhere on the stack, which sometimes causes stack corruption. This patch ensures that the result is written to some static scratch space where it can do no harm. PR-URL: https://github.com/libuv/libuv/pull/49 Reviewed-By: Ben Noordhuis Reviewed-By: Marc Schlaich Reviewed-By: Saúl Ibarra Corretgé --- src/win/internal.h | 4 ++-- src/win/poll.c | 9 +++++++++ src/win/winsock.c | 12 ++++++------ 3 files changed, 17 insertions(+), 8 deletions(-) diff --git a/src/win/internal.h b/src/win/internal.h index 9920f704..f32d24a7 100644 --- a/src/win/internal.h +++ b/src/win/internal.h @@ -332,8 +332,8 @@ int WSAAPI uv_wsarecvfrom_workaround(SOCKET socket, WSABUF* buffers, int* addr_len, WSAOVERLAPPED *overlapped, LPWSAOVERLAPPED_COMPLETION_ROUTINE completion_routine); -int WSAAPI uv_msafd_poll(SOCKET socket, AFD_POLL_INFO* info, - OVERLAPPED* overlapped); +int WSAAPI uv_msafd_poll(SOCKET socket, AFD_POLL_INFO* info_in, + AFD_POLL_INFO* info_out, OVERLAPPED* overlapped); /* Whether there are any non-IFS LSPs stacked on TCP */ extern int uv_tcp_non_ifs_lsp_ipv4; diff --git a/src/win/poll.c b/src/win/poll.c index 76427b01..37242792 100644 --- a/src/win/poll.c +++ b/src/win/poll.c @@ -46,6 +46,8 @@ typedef struct uv_single_fd_set_s { static OVERLAPPED overlapped_dummy_; static uv_once_t overlapped_dummy_init_guard_ = UV_ONCE_INIT; +static AFD_POLL_INFO afd_poll_info_dummy_; + static void uv__init_overlapped_dummy(void) { HANDLE event; @@ -65,6 +67,11 @@ static OVERLAPPED* uv__get_overlapped_dummy() { } +static AFD_POLL_INFO* uv__get_afd_poll_info_dummy() { + return &afd_poll_info_dummy_; +} + + static void uv__fast_poll_submit_poll_req(uv_loop_t* loop, uv_poll_t* handle) { uv_req_t* req; AFD_POLL_INFO* afd_poll_info; @@ -107,6 +114,7 @@ static void uv__fast_poll_submit_poll_req(uv_loop_t* loop, uv_poll_t* handle) { memset(&req->overlapped, 0, sizeof req->overlapped); result = uv_msafd_poll((SOCKET) handle->peer_socket, + afd_poll_info, afd_poll_info, &req->overlapped); if (result != 0 && WSAGetLastError() != WSA_IO_PENDING) { @@ -130,6 +138,7 @@ static int uv__fast_poll_cancel_poll_req(uv_loop_t* loop, uv_poll_t* handle) { result = uv_msafd_poll(handle->socket, &afd_poll_info, + uv__get_afd_poll_info_dummy(), uv__get_overlapped_dummy()); if (result == SOCKET_ERROR) { diff --git a/src/win/winsock.c b/src/win/winsock.c index cf6d0318..b91a2373 100644 --- a/src/win/winsock.c +++ b/src/win/winsock.c @@ -467,8 +467,8 @@ int WSAAPI uv_wsarecvfrom_workaround(SOCKET socket, WSABUF* buffers, } -int WSAAPI uv_msafd_poll(SOCKET socket, AFD_POLL_INFO* info, - OVERLAPPED* overlapped) { +int WSAAPI uv_msafd_poll(SOCKET socket, AFD_POLL_INFO* info_in, + AFD_POLL_INFO* info_out, OVERLAPPED* overlapped) { IO_STATUS_BLOCK iosb; IO_STATUS_BLOCK* iosb_ptr; HANDLE event = NULL; @@ -506,10 +506,10 @@ int WSAAPI uv_msafd_poll(SOCKET socket, AFD_POLL_INFO* info, apc_context, iosb_ptr, IOCTL_AFD_POLL, - info, - sizeof *info, - info, - sizeof *info); + info_in, + sizeof *info_in, + info_out, + sizeof *info_out); if (overlapped == NULL) { /* If this is a blocking operation, wait for the event to become */