From 75884678d7e7ef228c8f8f82b4c085258c70a823 Mon Sep 17 00:00:00 2001 From: theanarkh Date: Mon, 6 May 2024 20:56:36 +0800 Subject: [PATCH] src: add UV_PIPE_NO_TRUNCATE for bind in pipe_wrap.cc PR-URL: https://github.com/nodejs/node/pull/52347 Reviewed-By: Daeyeon Jeong Reviewed-By: James M Snell Reviewed-By: Benjamin Gruenbaum Reviewed-By: Matteo Collina Reviewed-By: Paolo Insogna Reviewed-By: Yagiz Nizipli --- doc/api/net.md | 10 +++--- src/pipe_wrap.cc | 11 ++++-- test/parallel/test-net-pipe-with-long-path.js | 36 +++++++++++++++++++ 3 files changed, 49 insertions(+), 8 deletions(-) create mode 100644 test/parallel/test-net-pipe-with-long-path.js diff --git a/doc/api/net.md b/doc/api/net.md index 22aa92e895974e..03d29170bc495c 100644 --- a/doc/api/net.md +++ b/doc/api/net.md @@ -37,11 +37,11 @@ sockets on other operating systems. [`socket.connect()`][] take a `path` parameter to identify IPC endpoints. On Unix, the local domain is also known as the Unix domain. The path is a -file system pathname. It gets truncated to an OS-dependent length of -`sizeof(sockaddr_un.sun_path) - 1`. Typical values are 107 bytes on Linux and -103 bytes on macOS. If a Node.js API abstraction creates the Unix domain socket, -it will unlink the Unix domain socket as well. For example, -[`net.createServer()`][] may create a Unix domain socket and +file system pathname. It will throw an error when the length of pathname is +greater than the length of `sizeof(sockaddr_un.sun_path)`. Typical values are +107 bytes on Linux and 103 bytes on macOS. If a Node.js API abstraction creates +the Unix domain socket, it will unlink the Unix domain socket as well. For +example, [`net.createServer()`][] may create a Unix domain socket and [`server.close()`][] will unlink it. But if a user creates the Unix domain socket outside of these abstractions, the user will need to remove it. The same applies when a Node.js API creates a Unix domain socket but the program then diff --git a/src/pipe_wrap.cc b/src/pipe_wrap.cc index 3f7cf26709e57f..359f99e79c484c 100644 --- a/src/pipe_wrap.cc +++ b/src/pipe_wrap.cc @@ -162,7 +162,8 @@ void PipeWrap::Bind(const FunctionCallbackInfo& args) { PipeWrap* wrap; ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder()); node::Utf8Value name(args.GetIsolate(), args[0]); - int err = uv_pipe_bind2(&wrap->handle_, *name, name.length(), 0); + int err = + uv_pipe_bind2(&wrap->handle_, *name, name.length(), UV_PIPE_NO_TRUNCATE); args.GetReturnValue().Set(err); } @@ -225,8 +226,12 @@ void PipeWrap::Connect(const FunctionCallbackInfo& args) { ConnectWrap* req_wrap = new ConnectWrap(env, req_wrap_obj, AsyncWrap::PROVIDER_PIPECONNECTWRAP); - int err = req_wrap->Dispatch( - uv_pipe_connect2, &wrap->handle_, *name, name.length(), 0, AfterConnect); + int err = req_wrap->Dispatch(uv_pipe_connect2, + &wrap->handle_, + *name, + name.length(), + UV_PIPE_NO_TRUNCATE, + AfterConnect); if (err) { delete req_wrap; } else { diff --git a/test/parallel/test-net-pipe-with-long-path.js b/test/parallel/test-net-pipe-with-long-path.js new file mode 100644 index 00000000000000..38e020f6698b0e --- /dev/null +++ b/test/parallel/test-net-pipe-with-long-path.js @@ -0,0 +1,36 @@ +'use strict'; +const common = require('../common'); +const assert = require('assert'); +const net = require('net'); +const fs = require('fs'); +const tmpdir = require('../common/tmpdir'); +tmpdir.refresh(); + +// Test UV_PIPE_NO_TRUNCATE + +// See pipe_overlong_path in https://github.com/libuv/libuv/blob/master/test/test-pipe-bind-error.c +if (common.isWindows) { + common.skip('UV_PIPE_NO_TRUNCATE is not supported on window'); +} + +// See https://github.com/libuv/libuv/issues/4231 +const pipePath = `${tmpdir.path}/${'x'.repeat(10000)}.sock`; + +const server = net.createServer() + .listen(pipePath) + // It may work on some operating systems + .on('listening', () => { + // The socket file must exsit + assert.ok(fs.existsSync(pipePath)); + const socket = net.connect(pipePath, common.mustCall(() => { + socket.destroy(); + server.close(); + })); + }) + .on('error', (error) => { + assert.ok(error.code === 'EINVAL', error.message); + net.connect(pipePath) + .on('error', common.mustCall((error) => { + assert.ok(error.code === 'EINVAL', error.message); + })); + });