commit abd0c882b37acbd26ec6805f3a8b68c4335c0584
parent b1c41a332d183c4cb003329f7c2a3f310f48273c
Author: Vlad <52591095+MeanderingProgrammer@users.noreply.github.com>
Date: Thu, 9 Oct 2025 18:04:02 -0700
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`.
Diffstat:
2 files changed, 12 insertions(+), 10 deletions(-)
diff --git 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
@@ -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.