mirror of
https://github.com/neovim/neovim.git
synced 2026-07-10 19:39:38 +00:00
fix(socket): --listen silently truncates long paths #40625
Problem:
A `--listen` path longer than the system socket path limit (~104 bytes on
macOS, 108 on Linux) is silently truncated by `uv_pipe_bind()`. Nvim either
serves a socket at a different path than `v:servername` reports, or fails with
an error that blames the full untruncated path (confusing):
nvim: Failed to --listen: address already in use: "<full path>"
Steps to reproduce:
$ nvim --listen /var/folders/g7/9y_ydbnj2fs_fvp8xf44p8gc0000gn/T//nvim/-Users-rpatterson-Projects-src-github.com-neovide-neovide --embed -p
nvim: Failed to --listen: address already in use: "/var/folders/g7/9y_ydbnj2fs_fvp8xf44p8gc0000gn/T//nvim/-Users-rpatterson-Projects-src-github.com-neovide-neovide"
$ ls /var/folders/g7/9y_ydbnj2fs_fvp8xf44p8gc0000gn/T//nvim/-Users-rpatterson-Projects-src-github.com-neovide-neovide
"/var/folders/g7/9y_ydbnj2fs_fvp8xf44p8gc0000gn/T//nvim/-Users-rpatterson-Projects-src-github.com-neovide-neovide": No such file or directory (os error 2)
$ ls -l /var/folders/g7/9y_ydbnj2fs_fvp8xf44p8gc0000gn/T//nvim/
srwxr-xr-x@ - rpatterson 31 Mar 10:24 -Users-rpatterson-Projects-src-github.com-neovid
Solution:
Bind with `uv_pipe_bind2()` and `UV_PIPE_NO_TRUNCATE` (libuv 1.46+), so
a too-long path fails up front with the actual reason:
nvim: Failed to --listen: invalid argument: "<full path>"
This commit is contained in:
committed by
GitHub
parent
a54a7f6a78
commit
de141b4679
@@ -169,7 +169,8 @@ int socket_watcher_start(SocketWatcher *watcher, int backlog, socket_cb cb)
|
||||
}
|
||||
uv_freeaddrinfo(watcher->uv.tcp.addrinfo);
|
||||
} else {
|
||||
result = uv_pipe_bind(&watcher->uv.pipe.handle, watcher->addr);
|
||||
result = uv_pipe_bind2(&watcher->uv.pipe.handle, watcher->addr, strlen(watcher->addr),
|
||||
UV_PIPE_NO_TRUNCATE);
|
||||
|
||||
// If bind failed with EACCES/EADDRINUSE, check if socket is stale
|
||||
if (result == UV_EACCES || result == UV_EADDRINUSE) {
|
||||
@@ -196,7 +197,8 @@ int socket_watcher_start(SocketWatcher *watcher, int backlog, socket_cb cb)
|
||||
watcher->stream->data = watcher;
|
||||
|
||||
// Retry bind with fresh handle
|
||||
result = uv_pipe_bind(&watcher->uv.pipe.handle, watcher->addr);
|
||||
result = uv_pipe_bind2(&watcher->uv.pipe.handle, watcher->addr, strlen(watcher->addr),
|
||||
UV_PIPE_NO_TRUNCATE);
|
||||
}
|
||||
} else {
|
||||
// Socket is alive - this is a real error
|
||||
|
||||
@@ -364,6 +364,15 @@ describe('startup --listen', function()
|
||||
('nvim.*: Failed to %%-%%-listen: [^:]+ already [^:]+: "%s"'):format(vim.pesc(in_use))
|
||||
)
|
||||
_test({ '--listen', '/' }, nil, 'nvim.*: Failed to %-%-listen: [^:]+: "/"')
|
||||
if not is_os('win') then
|
||||
-- Too-long path is rejected, not silently truncated. #38623
|
||||
local too_long = './Xtest-listen-' .. ('x'):rep(192)
|
||||
_test(
|
||||
{ '--listen', too_long },
|
||||
nil,
|
||||
('nvim.*: Failed to %%-%%-listen: invalid argument: "%s"'):format(vim.pesc(too_long))
|
||||
)
|
||||
end
|
||||
_test(
|
||||
{ '--listen', 'https://example.com' },
|
||||
nil,
|
||||
|
||||
@@ -376,8 +376,8 @@ describe('XDG defaults', function()
|
||||
if not is_os('win') then
|
||||
-- Broken XDG vars cause serverstart() to fail (except on Windows, where servernames are not
|
||||
-- informed by $XDG_STATE_HOME).
|
||||
t.matches('Failed to start server: no such file or directory', t.pcall_err(fn.serverstart))
|
||||
assert_log('Failed to start server: no such file or directory: /X/X/X', testlog, 10)
|
||||
t.matches('Failed to start server: invalid argument', t.pcall_err(fn.serverstart))
|
||||
assert_log('Failed to start server: invalid argument: /X/X/X', testlog, 10)
|
||||
end
|
||||
|
||||
local vimruntime, libdir = vimruntime_and_libdir()
|
||||
@@ -962,6 +962,13 @@ describe('stdpath()', function()
|
||||
it('$NVIM_APPNAME relative path', function()
|
||||
local tmpdir = t.tmpname(false)
|
||||
t.mkdir(tmpdir)
|
||||
-- Short runtime dir so the autogenerated server socket fits in sun_path even
|
||||
-- when $TMPDIR is deep (otherwise the server fails to bind, see #38623).
|
||||
local xdg_run = 'Xtest-appname-run'
|
||||
mkdir(xdg_run)
|
||||
finally(function()
|
||||
rmdir(xdg_run)
|
||||
end)
|
||||
|
||||
clear({
|
||||
args_rm = { '--listen' },
|
||||
@@ -969,6 +976,7 @@ describe('stdpath()', function()
|
||||
NVIM_APPNAME = 'relative/appname',
|
||||
NVIM_LOG_FILE = testlog,
|
||||
TMPDIR = tmpdir,
|
||||
XDG_RUNTIME_DIR = xdg_run,
|
||||
},
|
||||
})
|
||||
|
||||
|
||||
Reference in New Issue
Block a user