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`.
This commit is contained in:
Vlad
2025-10-09 18:04:02 -07:00
committed by GitHub
parent b1c41a332d
commit abd0c882b3
2 changed files with 12 additions and 10 deletions

View File

@@ -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);

View File

@@ -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.