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
This commit is contained in:
theanarkh 2022-06-11 12:32:08 +08:00 committed by GitHub
parent d938c104e1
commit 8bcd689c04
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 53 additions and 5 deletions

View File

@ -51,7 +51,9 @@ int uv_pipe_bind(uv_pipe_t* handle, const char* name) {
/* Already bound? */ /* Already bound? */
if (uv__stream_fd(handle) >= 0) if (uv__stream_fd(handle) >= 0)
return UV_EINVAL; return UV_EINVAL;
if (uv__is_closing(handle)) {
return UV_EINVAL;
}
/* Make a copy of the file name, it outlives this function's scope. */ /* Make a copy of the file name, it outlives this function's scope. */
pipe_fname = uv__strdup(name); pipe_fname = uv__strdup(name);
if (pipe_fname == NULL) if (pipe_fname == NULL)

View File

@ -641,7 +641,9 @@ done:
int uv_listen(uv_stream_t* stream, int backlog, uv_connection_cb cb) { int uv_listen(uv_stream_t* stream, int backlog, uv_connection_cb cb) {
int err; int err;
if (uv__is_closing(stream)) {
return UV_EINVAL;
}
switch (stream->type) { switch (stream->type) {
case UV_TCP: case UV_TCP:
err = uv__tcp_listen((uv_tcp_t*)stream, backlog, cb); err = uv__tcp_listen((uv_tcp_t*)stream, backlog, cb);

View File

@ -295,7 +295,9 @@ int uv_tcp_bind(uv_tcp_t* handle,
if (handle->type != UV_TCP) if (handle->type != UV_TCP)
return UV_EINVAL; return UV_EINVAL;
if (uv__is_closing(handle)) {
return UV_EINVAL;
}
if (addr->sa_family == AF_INET) if (addr->sa_family == AF_INET)
addrlen = sizeof(struct sockaddr_in); addrlen = sizeof(struct sockaddr_in);
else if (addr->sa_family == AF_INET6) else if (addr->sa_family == AF_INET6)

View File

@ -731,7 +731,9 @@ int uv_pipe_bind(uv_pipe_t* handle, const char* name) {
if (!name) { if (!name) {
return UV_EINVAL; return UV_EINVAL;
} }
if (uv__is_closing(handle)) {
return UV_EINVAL;
}
if (!(handle->flags & UV_HANDLE_PIPESERVER)) { if (!(handle->flags & UV_HANDLE_PIPESERVER)) {
handle->pipe.serv.pending_instances = default_pending_pipe_instances; handle->pipe.serv.pending_instances = default_pending_pipe_instances;
} }

View File

@ -29,7 +29,9 @@
int uv_listen(uv_stream_t* stream, int backlog, uv_connection_cb cb) { int uv_listen(uv_stream_t* stream, int backlog, uv_connection_cb cb) {
int err; int err;
if (uv__is_closing(stream)) {
return UV_EINVAL;
}
err = ERROR_INVALID_PARAMETER; err = ERROR_INVALID_PARAMETER;
switch (stream->type) { switch (stream->type) {
case UV_TCP: case UV_TCP:

View File

@ -122,6 +122,7 @@ TEST_DECLARE (tcp_bind_error_inval)
TEST_DECLARE (tcp_bind_localhost_ok) TEST_DECLARE (tcp_bind_localhost_ok)
TEST_DECLARE (tcp_bind_invalid_flags) TEST_DECLARE (tcp_bind_invalid_flags)
TEST_DECLARE (tcp_bind_writable_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_listen_without_bind)
TEST_DECLARE (tcp_connect_error_fault) TEST_DECLARE (tcp_connect_error_fault)
TEST_DECLARE (tcp_connect_timeout) TEST_DECLARE (tcp_connect_timeout)
@ -192,6 +193,7 @@ TEST_DECLARE (pipe_bind_error_addrnotavail)
TEST_DECLARE (pipe_bind_error_inval) TEST_DECLARE (pipe_bind_error_inval)
TEST_DECLARE (pipe_connect_multiple) TEST_DECLARE (pipe_connect_multiple)
TEST_DECLARE (pipe_listen_without_bind) 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_bad_name)
TEST_DECLARE (pipe_connect_to_file) TEST_DECLARE (pipe_connect_to_file)
TEST_DECLARE (pipe_connect_on_prepare) TEST_DECLARE (pipe_connect_on_prepare)
@ -697,6 +699,7 @@ TASK_LIST_START
TEST_ENTRY (tcp_bind_localhost_ok) TEST_ENTRY (tcp_bind_localhost_ok)
TEST_ENTRY (tcp_bind_invalid_flags) TEST_ENTRY (tcp_bind_invalid_flags)
TEST_ENTRY (tcp_bind_writable_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_listen_without_bind)
TEST_ENTRY (tcp_connect_error_fault) TEST_ENTRY (tcp_connect_error_fault)
TEST_ENTRY (tcp_connect_timeout) TEST_ENTRY (tcp_connect_timeout)
@ -775,6 +778,7 @@ TASK_LIST_START
TEST_ENTRY (pipe_bind_error_inval) TEST_ENTRY (pipe_bind_error_inval)
TEST_ENTRY (pipe_connect_multiple) TEST_ENTRY (pipe_connect_multiple)
TEST_ENTRY (pipe_listen_without_bind) TEST_ENTRY (pipe_listen_without_bind)
TEST_ENTRY (pipe_bind_or_listen_error_after_close)
TEST_ENTRY (pipe_getsockname) TEST_ENTRY (pipe_getsockname)
TEST_ENTRY (pipe_getsockname_abstract) TEST_ENTRY (pipe_getsockname_abstract)
TEST_ENTRY (pipe_getsockname_blocking) TEST_ENTRY (pipe_getsockname_blocking)

View File

@ -137,3 +137,19 @@ TEST_IMPL(pipe_listen_without_bind) {
MAKE_VALGRIND_HAPPY(); MAKE_VALGRIND_HAPPY();
return 0; 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;
}

View File

@ -297,3 +297,21 @@ TEST_IMPL(tcp_bind_writable_flags) {
MAKE_VALGRIND_HAPPY(); MAKE_VALGRIND_HAPPY();
return 0; 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;
}