From abd0c882b37acbd26ec6805f3a8b68c4335c0584 Mon Sep 17 00:00:00 2001 From: Vlad <52591095+MeanderingProgrammer@users.noreply.github.com> Date: Thu, 9 Oct 2025 18:04:02 -0700 Subject: [PATCH] fix(rpc): handle more cases when identifying loopback #36100 Problem: On MacOS it is a relatively common pattern to set XDG_RUNTIME_DIR under `/tmp` or `/var`. Both of these are symlinks to `/private/tmp` and `/private/var`. When checking for loopback the input address is normalized using `fix_fname`, however this is not applied to the addresses of the sockets. As a result of one address being normalized and the other not the comparison would fail. Solution: Normalize both sides of the comparison using `fix_fname`. --- src/nvim/channel.c | 6 +----- src/nvim/msgpack_rpc/server.c | 16 +++++++++++----- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/src/nvim/channel.c b/src/nvim/channel.c index fd30234532..cae3d2b7e7 100644 --- a/src/nvim/channel.c +++ b/src/nvim/channel.c @@ -41,7 +41,6 @@ #include "nvim/os/fs.h" #include "nvim/os/os_defs.h" #include "nvim/os/shell.h" -#include "nvim/path.h" #include "nvim/terminal.h" #include "nvim/types_defs.h" @@ -461,10 +460,7 @@ uint64_t channel_connect(bool tcp, const char *address, bool rpc, CallbackReader Channel *channel; if (!tcp && rpc) { - char *path = fix_fname(address); - bool loopback = server_owns_pipe_address(path); - xfree(path); - if (loopback) { + if (server_owns_pipe_address(address)) { // Create a loopback channel. This avoids deadlock if nvim connects to // its own named pipe. channel = channel_alloc(kChannelStreamInternal); diff --git a/src/nvim/msgpack_rpc/server.c b/src/nvim/msgpack_rpc/server.c index 54ed66e763..1c839ac9d2 100644 --- a/src/nvim/msgpack_rpc/server.c +++ b/src/nvim/msgpack_rpc/server.c @@ -19,6 +19,7 @@ #include "nvim/os/os.h" #include "nvim/os/os_defs.h" #include "nvim/os/stdpaths_defs.h" +#include "nvim/path.h" #include "nvim/types_defs.h" #define MAX_CONNECTIONS 32 @@ -135,15 +136,20 @@ char *server_address_new(const char *name) } /// Check if this instance owns a pipe address. -/// The argument must already be resolved to an absolute path! -bool server_owns_pipe_address(const char *path) +bool server_owns_pipe_address(const char *address) { + bool result = false; + char *path = fix_fname(address); for (int i = 0; i < watchers.ga_len; i++) { - if (!strcmp(path, ((SocketWatcher **)watchers.ga_data)[i]->addr)) { - return true; + char *addr = fix_fname(((SocketWatcher **)watchers.ga_data)[i]->addr); + result = strequal(path, addr); + xfree(addr); + if (result) { + break; } } - return false; + xfree(path); + return result; } /// Starts listening for RPC calls.