From fb5df542ace7d6735a9e8e09d7d8bb6b8abdc459 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sa=C3=BAl=20Ibarra=20Corretg=C3=A9?= Date: Thu, 18 Jun 2015 00:41:44 +0200 Subject: [PATCH] unix, win: prevent replacing fd in uv_{udp,tcp,pipe}_t PR-URL: https://github.com/libuv/libuv/pull/400 Reviewed-By: Ben Noordhuis --- src/unix/stream.c | 3 +++ src/unix/udp.c | 2 +- src/win/pipe.c | 3 +++ src/win/tcp.c | 3 ++- src/win/udp.c | 3 ++- test/test-list.h | 4 ++++ test/test-tcp-open.c | 38 ++++++++++++++++++++++++++++++++++++++ test/test-udp-open.c | 38 ++++++++++++++++++++++++++++++++++++++ 8 files changed, 91 insertions(+), 3 deletions(-) diff --git a/src/unix/stream.c b/src/unix/stream.c index 7ad1658c..b70ef95d 100644 --- a/src/unix/stream.c +++ b/src/unix/stream.c @@ -391,6 +391,9 @@ int uv__stream_open(uv_stream_t* stream, int fd, int flags) { int enable; #endif + if (!(stream->io_watcher.fd == -1 || stream->io_watcher.fd == fd)) + return -EBUSY; + assert(fd >= 0); stream->flags |= flags; diff --git a/src/unix/udp.c b/src/unix/udp.c index f85ab147..2d04e9f9 100644 --- a/src/unix/udp.c +++ b/src/unix/udp.c @@ -569,7 +569,7 @@ int uv_udp_open(uv_udp_t* handle, uv_os_sock_t sock) { /* Check for already active socket. */ if (handle->io_watcher.fd != -1) - return -EALREADY; /* FIXME(bnoordhuis) Should be -EBUSY. */ + return -EBUSY; err = uv__nonblock(sock, 1); if (err) diff --git a/src/win/pipe.c b/src/win/pipe.c index 8edfe42a..06cf0db2 100644 --- a/src/win/pipe.c +++ b/src/win/pipe.c @@ -254,6 +254,9 @@ static int uv_set_pipe_handle(uv_loop_t* loop, DWORD current_mode = 0; DWORD err = 0; + if (handle->handle != INVALID_HANDLE_VALUE) + return UV_EBUSY; + if (!SetNamedPipeHandleState(pipeHandle, &mode, NULL, NULL)) { err = GetLastError(); if (err == ERROR_ACCESS_DENIED) { diff --git a/src/win/tcp.c b/src/win/tcp.c index da89f28d..536deb0a 100644 --- a/src/win/tcp.c +++ b/src/win/tcp.c @@ -84,7 +84,8 @@ static int uv_tcp_set_socket(uv_loop_t* loop, uv_tcp_t* handle, int non_ifs_lsp; int err; - assert(handle->socket == INVALID_SOCKET); + if (handle->socket != INVALID_SOCKET) + return UV_EBUSY; /* Set the socket to nonblocking mode */ if (ioctlsocket(socket, FIONBIO, &yes) == SOCKET_ERROR) { diff --git a/src/win/udp.c b/src/win/udp.c index 197e5d82..def50ac4 100644 --- a/src/win/udp.c +++ b/src/win/udp.c @@ -61,7 +61,8 @@ static int uv_udp_set_socket(uv_loop_t* loop, uv_udp_t* handle, SOCKET socket, WSAPROTOCOL_INFOW info; int opt_len; - assert(handle->socket == INVALID_SOCKET); + if (handle->socket != INVALID_SOCKET) + return UV_EBUSY; /* Set the socket to nonblocking mode */ if (ioctlsocket(socket, FIONBIO, &yes) == SOCKET_ERROR) { diff --git a/test/test-list.h b/test/test-list.h index 1e4018c9..2999d42b 100644 --- a/test/test-list.h +++ b/test/test-list.h @@ -66,6 +66,7 @@ TEST_DECLARE (tcp_write_fail) TEST_DECLARE (tcp_try_write) TEST_DECLARE (tcp_write_queue_order) TEST_DECLARE (tcp_open) +TEST_DECLARE (tcp_open_twice) TEST_DECLARE (tcp_connect_error_after_write) TEST_DECLARE (tcp_shutdown_after_write) TEST_DECLARE (tcp_bind_error_addrinuse) @@ -110,6 +111,7 @@ TEST_DECLARE (udp_options) TEST_DECLARE (udp_options6) TEST_DECLARE (udp_no_autobind) TEST_DECLARE (udp_open) +TEST_DECLARE (udp_open_twice) TEST_DECLARE (udp_try_send) TEST_DECLARE (pipe_bind_error_addrinuse) TEST_DECLARE (pipe_bind_error_addrnotavail) @@ -393,6 +395,7 @@ TASK_LIST_START TEST_ENTRY (tcp_open) TEST_HELPER (tcp_open, tcp4_echo_server) + TEST_ENTRY (tcp_open_twice) TEST_ENTRY (tcp_shutdown_after_write) TEST_HELPER (tcp_shutdown_after_write, tcp4_echo_server) @@ -447,6 +450,7 @@ TASK_LIST_START TEST_ENTRY (udp_open) TEST_HELPER (udp_open, udp4_echo_server) + TEST_ENTRY (udp_open_twice) TEST_ENTRY (pipe_bind_error_addrinuse) TEST_ENTRY (pipe_bind_error_addrnotavail) diff --git a/test/test-tcp-open.c b/test/test-tcp-open.c index edeacc70..6c8d43d0 100644 --- a/test/test-tcp-open.c +++ b/test/test-tcp-open.c @@ -71,6 +71,17 @@ static uv_os_sock_t create_tcp_socket(void) { } +static void close_socket(uv_os_sock_t sock) { + int r; +#ifdef _WIN32 + r = closesocket(sock); +#else + r = close(sock); +#endif + ASSERT(r == 0); +} + + static void alloc_cb(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf) { @@ -180,3 +191,30 @@ TEST_IMPL(tcp_open) { MAKE_VALGRIND_HAPPY(); return 0; } + + +TEST_IMPL(tcp_open_twice) { + uv_tcp_t client; + uv_os_sock_t sock1, sock2; + int r; + + startup(); + sock1 = create_tcp_socket(); + sock2 = create_tcp_socket(); + + r = uv_tcp_init(uv_default_loop(), &client); + ASSERT(r == 0); + + r = uv_tcp_open(&client, sock1); + ASSERT(r == 0); + + r = uv_tcp_open(&client, sock2); + ASSERT(r == UV_EBUSY); + close_socket(sock2); + + uv_close((uv_handle_t*) &client, NULL); + uv_run(uv_default_loop(), UV_RUN_DEFAULT); + + MAKE_VALGRIND_HAPPY(); + return 0; +} diff --git a/test/test-udp-open.c b/test/test-udp-open.c index b2b61177..4d77f45d 100644 --- a/test/test-udp-open.c +++ b/test/test-udp-open.c @@ -67,6 +67,17 @@ static uv_os_sock_t create_udp_socket(void) { } +static void close_socket(uv_os_sock_t sock) { + int r; +#ifdef _WIN32 + r = closesocket(sock); +#else + r = close(sock); +#endif + ASSERT(r == 0); +} + + static void alloc_cb(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf) { @@ -164,3 +175,30 @@ TEST_IMPL(udp_open) { MAKE_VALGRIND_HAPPY(); return 0; } + + +TEST_IMPL(udp_open_twice) { + uv_udp_t client; + uv_os_sock_t sock1, sock2; + int r; + + startup(); + sock1 = create_udp_socket(); + sock2 = create_udp_socket(); + + r = uv_udp_init(uv_default_loop(), &client); + ASSERT(r == 0); + + r = uv_udp_open(&client, sock1); + ASSERT(r == 0); + + r = uv_udp_open(&client, sock2); + ASSERT(r == UV_EBUSY); + close_socket(sock2); + + uv_close((uv_handle_t*) &client, NULL); + uv_run(uv_default_loop(), UV_RUN_DEFAULT); + + MAKE_VALGRIND_HAPPY(); + return 0; +}