diff --git a/docs/src/pipe.rst b/docs/src/pipe.rst index 9d95b206..4abdc65e 100644 --- a/docs/src/pipe.rst +++ b/docs/src/pipe.rst @@ -68,15 +68,18 @@ API Bind the pipe to a file path (Unix) or a name (Windows). - ``flags`` must be zero. Returns ``UV_EINVAL`` for unsupported flags - without performing the bind operation. + ``flags`` must be zero or ``UV_PIPE_NO_TRUNCATE``. Returns ``UV_EINVAL`` + for unsupported flags without performing the bind operation. Supports Linux abstract namespace sockets. ``namelen`` must include the leading nul byte but not the trailing nul byte. + .. versionadded:: 1.46.0 + .. note:: Paths on Unix get truncated to ``sizeof(sockaddr_un.sun_path)`` bytes, - typically between 92 and 108 bytes. + typically between 92 and 108 bytes, unless the ``UV_PIPE_NO_TRUNCATE`` + flag is specified, in which case an ``UV_EINVAL`` error is returned. .. c:function:: void uv_pipe_connect(uv_connect_t* req, uv_pipe_t* handle, const char* name, uv_connect_cb cb) @@ -95,15 +98,18 @@ API Connect to the Unix domain socket or the Windows named pipe. - ``flags`` must be zero. Returns ``UV_EINVAL`` for unsupported flags - without performing the connect operation. + ``flags`` must be zero or ``UV_PIPE_NO_TRUNCATE``. Returns ``UV_EINVAL`` + for unsupported flags without performing the connect operation. Supports Linux abstract namespace sockets. ``namelen`` must include the leading nul byte but not the trailing nul byte. + .. versionadded:: 1.46.0 + .. note:: Paths on Unix get truncated to ``sizeof(sockaddr_un.sun_path)`` bytes, - typically between 92 and 108 bytes. + typically between 92 and 108 bytes, unless the ``UV_PIPE_NO_TRUNCATE`` + flag is specified, in which case an ``UV_EINVAL`` error is returned. .. c:function:: int uv_pipe_getsockname(const uv_pipe_t* handle, char* buffer, size_t* size) diff --git a/include/uv.h b/include/uv.h index 0f624f4d..f68ff083 100644 --- a/include/uv.h +++ b/include/uv.h @@ -807,6 +807,10 @@ inline int uv_tty_set_mode(uv_tty_t* handle, int mode) { UV_EXTERN uv_handle_type uv_guess_handle(uv_file file); +enum { + UV_PIPE_NO_TRUNCATE = 1u << 0 +}; + /* * uv_pipe_t is a subclass of uv_stream_t. * diff --git a/src/unix/pipe.c b/src/unix/pipe.c index 823deb3d..d332f351 100644 --- a/src/unix/pipe.c +++ b/src/unix/pipe.c @@ -56,7 +56,7 @@ int uv_pipe_bind2(uv_pipe_t* handle, pipe_fname = NULL; - if (flags != 0) + if (flags & ~UV_PIPE_NO_TRUNCATE) return UV_EINVAL; if (name == NULL) @@ -71,6 +71,10 @@ int uv_pipe_bind2(uv_pipe_t* handle, return UV_EINVAL; #endif + if (flags & UV_PIPE_NO_TRUNCATE) + if (namelen > sizeof(saddr.sun_path)) + return UV_EINVAL; + /* Truncate long paths. Documented behavior. */ if (namelen > sizeof(saddr.sun_path)) namelen = sizeof(saddr.sun_path); @@ -221,7 +225,7 @@ int uv_pipe_connect2(uv_connect_t* req, int err; int r; - if (flags != 0) + if (flags & ~UV_PIPE_NO_TRUNCATE) return UV_EINVAL; if (name == NULL) @@ -236,6 +240,10 @@ int uv_pipe_connect2(uv_connect_t* req, return UV_EINVAL; #endif + if (flags & UV_PIPE_NO_TRUNCATE) + if (namelen > sizeof(saddr.sun_path)) + return UV_EINVAL; + /* Truncate long paths. Documented behavior. */ if (namelen > sizeof(saddr.sun_path)) namelen = sizeof(saddr.sun_path); diff --git a/src/win/pipe.c b/src/win/pipe.c index a3daa3b7..f0cac382 100644 --- a/src/win/pipe.c +++ b/src/win/pipe.c @@ -706,7 +706,7 @@ int uv_pipe_bind2(uv_pipe_t* handle, int i, err, nameSize; uv_pipe_accept_t* req; - if (flags != 0) { + if (flags & ~UV_PIPE_NO_TRUNCATE) { return UV_EINVAL; } @@ -722,6 +722,12 @@ int uv_pipe_bind2(uv_pipe_t* handle, return UV_EINVAL; } + if (flags & UV_PIPE_NO_TRUNCATE) { + if (namelen > 256) { + return UV_EINVAL; + } + } + if (handle->flags & UV_HANDLE_BOUND) { return UV_EINVAL; } @@ -859,7 +865,7 @@ int uv_pipe_connect2(uv_connect_t* req, HANDLE pipeHandle = INVALID_HANDLE_VALUE; DWORD duplex_flags; - if (flags != 0) { + if (flags & ~UV_PIPE_NO_TRUNCATE) { return UV_EINVAL; } @@ -875,6 +881,12 @@ int uv_pipe_connect2(uv_connect_t* req, return UV_EINVAL; } + if (flags & UV_PIPE_NO_TRUNCATE) { + if (namelen > 256) { + return UV_EINVAL; + } + } + UV_REQ_INIT(req, UV_CONNECT); req->handle = (uv_stream_t*) handle; req->cb = cb; diff --git a/test/test-list.h b/test/test-list.h index 6da78123..b2c88170 100644 --- a/test/test-list.h +++ b/test/test-list.h @@ -198,6 +198,7 @@ TEST_DECLARE (pipe_connect_close_multiple) TEST_DECLARE (pipe_connect_multiple) TEST_DECLARE (pipe_listen_without_bind) TEST_DECLARE (pipe_bind_or_listen_error_after_close) +TEST_DECLARE (pipe_overlong_path) TEST_DECLARE (pipe_connect_bad_name) TEST_DECLARE (pipe_connect_to_file) TEST_DECLARE (pipe_connect_on_prepare) @@ -799,6 +800,7 @@ TASK_LIST_START TEST_ENTRY (pipe_connect_multiple) TEST_ENTRY (pipe_listen_without_bind) TEST_ENTRY (pipe_bind_or_listen_error_after_close) + TEST_ENTRY (pipe_overlong_path) 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 88ece6ba..f8626302 100644 --- a/test/test-pipe-bind-error.c +++ b/test/test-pipe-bind-error.c @@ -153,3 +153,27 @@ TEST_IMPL(pipe_bind_or_listen_error_after_close) { MAKE_VALGRIND_HAPPY(uv_default_loop()); return 0; } + +TEST_IMPL(pipe_overlong_path) { + char path[512]; + uv_pipe_t pipe; + uv_connect_t req; + + memset(path, '@', sizeof(path)); + ASSERT_OK(uv_pipe_init(uv_default_loop(), &pipe, 0)); + ASSERT_EQ(UV_EINVAL, + uv_pipe_bind2(&pipe, path, sizeof(path), UV_PIPE_NO_TRUNCATE)); + ASSERT_EQ(UV_EINVAL, + uv_pipe_connect2(&req, + &pipe, + path, + sizeof(path), + UV_PIPE_NO_TRUNCATE, + (uv_connect_cb) abort)); + uv_close((uv_handle_t*) &pipe, NULL); + ASSERT_OK(uv_run(uv_default_loop(), UV_RUN_DEFAULT)); + + MAKE_VALGRIND_HAPPY(uv_default_loop()); + return 0; + +}