From 8bcd689c048af5aab26842ac5ff903fa3192d57c Mon Sep 17 00:00:00 2001 From: theanarkh <2923878201@qq.com> Date: Sat, 11 Jun 2022 12:32:08 +0800 Subject: [PATCH] tcp,pipe: fail `bind` or `listen` after `close` (#3641) Return `UV_EINVAL` in `bind` and `listen` when `handle` is `UV_HANDLE_CLOSING` or `UV_HANDLE_CLOSED`. Fixes: https://github.com/libuv/libuv/issues/3503 --- src/unix/pipe.c | 4 +++- src/unix/stream.c | 4 +++- src/uv-common.c | 4 +++- src/win/pipe.c | 4 +++- src/win/stream.c | 4 +++- test/test-list.h | 4 ++++ test/test-pipe-bind-error.c | 16 ++++++++++++++++ test/test-tcp-bind-error.c | 18 ++++++++++++++++++ 8 files changed, 53 insertions(+), 5 deletions(-) diff --git a/src/unix/pipe.c b/src/unix/pipe.c index f373c86e..e8cfa148 100644 --- a/src/unix/pipe.c +++ b/src/unix/pipe.c @@ -51,7 +51,9 @@ int uv_pipe_bind(uv_pipe_t* handle, const char* name) { /* Already bound? */ if (uv__stream_fd(handle) >= 0) return UV_EINVAL; - + if (uv__is_closing(handle)) { + return UV_EINVAL; + } /* Make a copy of the file name, it outlives this function's scope. */ pipe_fname = uv__strdup(name); if (pipe_fname == NULL) diff --git a/src/unix/stream.c b/src/unix/stream.c index 9615673a..93c6b934 100644 --- a/src/unix/stream.c +++ b/src/unix/stream.c @@ -641,7 +641,9 @@ done: int uv_listen(uv_stream_t* stream, int backlog, uv_connection_cb cb) { int err; - + if (uv__is_closing(stream)) { + return UV_EINVAL; + } switch (stream->type) { case UV_TCP: err = uv__tcp_listen((uv_tcp_t*)stream, backlog, cb); diff --git a/src/uv-common.c b/src/uv-common.c index f43dd3de..efc9eb50 100644 --- a/src/uv-common.c +++ b/src/uv-common.c @@ -295,7 +295,9 @@ int uv_tcp_bind(uv_tcp_t* handle, if (handle->type != UV_TCP) return UV_EINVAL; - + if (uv__is_closing(handle)) { + return UV_EINVAL; + } if (addr->sa_family == AF_INET) addrlen = sizeof(struct sockaddr_in); else if (addr->sa_family == AF_INET6) diff --git a/src/win/pipe.c b/src/win/pipe.c index 67e28300..08950d6a 100644 --- a/src/win/pipe.c +++ b/src/win/pipe.c @@ -731,7 +731,9 @@ int uv_pipe_bind(uv_pipe_t* handle, const char* name) { if (!name) { return UV_EINVAL; } - + if (uv__is_closing(handle)) { + return UV_EINVAL; + } if (!(handle->flags & UV_HANDLE_PIPESERVER)) { handle->pipe.serv.pending_instances = default_pending_pipe_instances; } diff --git a/src/win/stream.c b/src/win/stream.c index b304d170..19af0568 100644 --- a/src/win/stream.c +++ b/src/win/stream.c @@ -29,7 +29,9 @@ int uv_listen(uv_stream_t* stream, int backlog, uv_connection_cb cb) { int err; - + if (uv__is_closing(stream)) { + return UV_EINVAL; + } err = ERROR_INVALID_PARAMETER; switch (stream->type) { case UV_TCP: diff --git a/test/test-list.h b/test/test-list.h index 90393393..e74c1009 100644 --- a/test/test-list.h +++ b/test/test-list.h @@ -122,6 +122,7 @@ TEST_DECLARE (tcp_bind_error_inval) TEST_DECLARE (tcp_bind_localhost_ok) TEST_DECLARE (tcp_bind_invalid_flags) TEST_DECLARE (tcp_bind_writable_flags) +TEST_DECLARE (tcp_bind_or_listen_error_after_close) TEST_DECLARE (tcp_listen_without_bind) TEST_DECLARE (tcp_connect_error_fault) TEST_DECLARE (tcp_connect_timeout) @@ -192,6 +193,7 @@ TEST_DECLARE (pipe_bind_error_addrnotavail) TEST_DECLARE (pipe_bind_error_inval) TEST_DECLARE (pipe_connect_multiple) TEST_DECLARE (pipe_listen_without_bind) +TEST_DECLARE (pipe_bind_or_listen_error_after_close) TEST_DECLARE (pipe_connect_bad_name) TEST_DECLARE (pipe_connect_to_file) TEST_DECLARE (pipe_connect_on_prepare) @@ -697,6 +699,7 @@ TASK_LIST_START TEST_ENTRY (tcp_bind_localhost_ok) TEST_ENTRY (tcp_bind_invalid_flags) TEST_ENTRY (tcp_bind_writable_flags) + TEST_ENTRY (tcp_bind_or_listen_error_after_close) TEST_ENTRY (tcp_listen_without_bind) TEST_ENTRY (tcp_connect_error_fault) TEST_ENTRY (tcp_connect_timeout) @@ -775,6 +778,7 @@ TASK_LIST_START TEST_ENTRY (pipe_bind_error_inval) TEST_ENTRY (pipe_connect_multiple) TEST_ENTRY (pipe_listen_without_bind) + TEST_ENTRY (pipe_bind_or_listen_error_after_close) TEST_ENTRY (pipe_getsockname) TEST_ENTRY (pipe_getsockname_abstract) TEST_ENTRY (pipe_getsockname_blocking) diff --git a/test/test-pipe-bind-error.c b/test/test-pipe-bind-error.c index ce35052f..aacde456 100644 --- a/test/test-pipe-bind-error.c +++ b/test/test-pipe-bind-error.c @@ -137,3 +137,19 @@ TEST_IMPL(pipe_listen_without_bind) { MAKE_VALGRIND_HAPPY(); return 0; } + +TEST_IMPL(pipe_bind_or_listen_error_after_close) { + uv_pipe_t server; + + ASSERT_EQ(uv_pipe_init(uv_default_loop(), &server, 0), 0); + uv_close((uv_handle_t*) &server, NULL); + + ASSERT_EQ(uv_pipe_bind(&server, TEST_PIPENAME), UV_EINVAL); + + ASSERT_EQ(uv_listen((uv_stream_t*) &server, SOMAXCONN, NULL), UV_EINVAL); + + ASSERT_EQ(uv_run(uv_default_loop(), UV_RUN_DEFAULT), 0); + + MAKE_VALGRIND_HAPPY(); + return 0; +} diff --git a/test/test-tcp-bind-error.c b/test/test-tcp-bind-error.c index fdd1fe07..c3ca6ec8 100644 --- a/test/test-tcp-bind-error.c +++ b/test/test-tcp-bind-error.c @@ -297,3 +297,21 @@ TEST_IMPL(tcp_bind_writable_flags) { MAKE_VALGRIND_HAPPY(); return 0; } + +TEST_IMPL(tcp_bind_or_listen_error_after_close) { + uv_tcp_t tcp; + struct sockaddr_in addr; + + memset(&addr, 0, sizeof(addr)); + addr.sin_addr.s_addr = htonl(INADDR_ANY); + addr.sin_port = htons(9999); + addr.sin_family = AF_INET; + + ASSERT_EQ(uv_tcp_init(uv_default_loop(), &tcp), 0); + uv_close((uv_handle_t*) &tcp, NULL); + ASSERT_EQ(uv_tcp_bind(&tcp, (struct sockaddr*) &addr, 0), UV_EINVAL); + ASSERT_EQ(uv_listen((uv_stream_t*) &tcp, 5, NULL), UV_EINVAL); + ASSERT_EQ(uv_run(uv_default_loop(), UV_RUN_DEFAULT), 0); + MAKE_VALGRIND_HAPPY(); + return 0; +}