win: avoid stack corruption when closing a poll handle

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 <info@bnoordhuis.nl>
Reviewed-By: Marc Schlaich <marc.schlaich@gmail.com>
Reviewed-By: Saúl Ibarra Corretgé <saghul@gmail.com>
This commit is contained in:
Bert Belder 2014-12-09 22:53:05 +01:00
parent 152c35d54d
commit 48d39345bc
3 changed files with 17 additions and 8 deletions

View File

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

View File

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

View File

@ -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 */