Skip to content

Commit

Permalink
unix,win: add UV_PIPE_NO_TRUNCATE flag (libuv#4040)
Browse files Browse the repository at this point in the history
Libuv's default behavior is to truncate long Unix socket paths. The flag
tells it to return an error instead.

Fixes: libuv#4036
  • Loading branch information
bnoordhuis authored Jun 6, 2023
1 parent b9b6db0 commit 2f1614b
Show file tree
Hide file tree
Showing 6 changed files with 66 additions and 10 deletions.
18 changes: 12 additions & 6 deletions docs/src/pipe.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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)
Expand Down
4 changes: 4 additions & 0 deletions include/uv.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*
Expand Down
12 changes: 10 additions & 2 deletions src/unix/pipe.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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);
Expand Down Expand Up @@ -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)
Expand All @@ -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);
Expand Down
16 changes: 14 additions & 2 deletions src/win/pipe.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand All @@ -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;
}
Expand Down Expand Up @@ -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;
}

Expand All @@ -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;
Expand Down
2 changes: 2 additions & 0 deletions test/test-list.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand Down
24 changes: 24 additions & 0 deletions test/test-pipe-bind-error.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

}

0 comments on commit 2f1614b

Please sign in to comment.