1
0
mirror of https://github.com/libuv/libuv synced 2025-03-28 21:13:16 +00:00

Merge ebce661828aa06101e3aa31790c72e7aae20af49 into ea1cf034bef1ee39cf453b5b37b98be153541453

This commit is contained in:
Edy Silva 2025-03-18 08:37:33 +05:30 committed by GitHub
commit 96752d4cec
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 97 additions and 18 deletions

View File

@ -29,6 +29,40 @@
#include <unistd.h>
#include <stdlib.h>
struct uv__sockaddr_un_path {
char pad[offsetof(struct sockaddr_un, sun_path)];
#ifdef SOCK_MAXADDRLEN
/* macOS and the BSDs support paths > sizeof(su.sun_path).
* SOCK_MAXADDRLEN is, to the best of my knowledge, always 255.
* Minus the two byte header, that leaves 253 bytes for the path.
*/
char path[SOCK_MAXADDRLEN - offsetof(struct sockaddr_un, sun_path)];
#else
char path[sizeof(((struct sockaddr_un*)0)->sun_path)];
#endif
};
union uv__sockaddr_un {
struct sockaddr sa;
struct uv__sockaddr_un_path up;
};
static void uv__prep_sockaddr_un(union uv__sockaddr_un* s, const char* path) {
size_t len;
len = 1 + strlen(path);
if (len > sizeof(s->up.path))
len = sizeof(s->up.path);
memset(s, 0, sizeof(*s));
#ifdef SOCK_MAXADDRLEN
s->sa.sa_len = len;
#endif
s->sa.sa_family = AF_UNIX;
memcpy(s->up.path, path, len);
}
/* Does the file path contain embedded nul bytes? */
static int includes_nul(const char *s, size_t n) {
@ -122,11 +156,9 @@ int uv_pipe_bind2(uv_pipe_t* handle,
goto err_socket;
sockfd = err;
memset(&saddr, 0, sizeof saddr);
memcpy(&saddr.sun_path, name, namelen);
saddr.sun_family = AF_UNIX;
uv__prep_sockaddr_un(&saddr, pipe_fname);
if (bind(sockfd, (struct sockaddr*)&saddr, addrlen)) {
if (bind(sockfd, &saddr.sa, sizeof(saddr))) {
err = UV__ERR(errno);
/* Convert ENOENT to EACCES for compatibility with Windows. */
if (err == UV_ENOENT)
@ -291,18 +323,10 @@ int uv_pipe_connect2(uv_connect_t* req,
handle->io_watcher.fd = err;
}
memset(&saddr, 0, sizeof saddr);
memcpy(&saddr.sun_path, name, namelen);
saddr.sun_family = AF_UNIX;
uv__prep_sockaddr_un(&saddr, name);
if (*name == '\0')
addrlen = offsetof(struct sockaddr_un, sun_path) + namelen;
else
addrlen = sizeof saddr;
do {
r = connect(uv__stream_fd(handle), (struct sockaddr*)&saddr, addrlen);
}
do
r = connect(uv__stream_fd(handle), &saddr.sa, sizeof(saddr));
while (r == -1 && errno == EINTR);
if (r == -1 && errno != EINPROGRESS) {
@ -349,6 +373,9 @@ static int uv__pipe_getsockpeername(const uv_pipe_t* handle,
uv__peersockfunc func,
char* buffer,
size_t* size) {
union uv__sockaddr_un saddr;
int addrlen;
#if defined(__linux__)
static const int is_linux = 1;
#else
@ -359,7 +386,10 @@ static int uv__pipe_getsockpeername(const uv_pipe_t* handle,
size_t slop;
char* p;
int err;
char* nul;
addrlen = sizeof(saddr);
memset(&saddr, 0, sizeof(saddr));
if (buffer == NULL || size == NULL || *size == 0)
return UV_EINVAL;
@ -367,8 +397,8 @@ static int uv__pipe_getsockpeername(const uv_pipe_t* handle,
memset(&sa, 0, addrlen);
err = uv__getsockpeername((const uv_handle_t*) handle,
func,
(struct sockaddr*) &sa,
(int*) &addrlen);
&saddr.sa,
&addrlen);
if (err < 0) {
*size = 0;
return err;
@ -391,7 +421,7 @@ static int uv__pipe_getsockpeername(const uv_pipe_t* handle,
return UV_ENOBUFS;
}
memcpy(buffer, sa.sun_path, addrlen);
memcpy(buffer, saddr.up.path, addrlen);
*size = addrlen;
/* only null-terminate if it's not an abstract socket */

View File

@ -212,6 +212,7 @@ TEST_DECLARE (pipe_getsockname)
TEST_DECLARE (pipe_getsockname_abstract)
TEST_DECLARE (pipe_getsockname_autobind)
TEST_DECLARE (pipe_getsockname_blocking)
TEST_DECLARE (pipe_getsockname_long_path)
TEST_DECLARE (pipe_pending_instances)
TEST_DECLARE (pipe_sendmsg)
TEST_DECLARE (pipe_server_close)
@ -840,6 +841,7 @@ TASK_LIST_START
TEST_ENTRY (pipe_getsockname_abstract)
TEST_ENTRY (pipe_getsockname_autobind)
TEST_ENTRY (pipe_getsockname_blocking)
TEST_ENTRY (pipe_getsockname_long_path)
TEST_ENTRY (pipe_pending_instances)
TEST_ENTRY (pipe_sendmsg)

View File

@ -26,6 +26,8 @@
#include <string.h>
#ifndef _WIN32
# include <sys/socket.h> /* SOCK_MAXADDRLEN */
# include <sys/un.h>
# include <unistd.h> /* close */
#else
# include <fcntl.h>
@ -368,3 +370,48 @@ TEST_IMPL(pipe_getsockname_blocking) {
MAKE_VALGRIND_HAPPY(uv_default_loop());
return 0;
}
static void long_path_connect_cb(uv_connect_t* req, int status) {
ASSERT_EQ(status, 0);
uv_close((uv_handle_t*) req->handle, NULL);
}
/* macOS and the BSDs support paths > sizeof(su.sun_path). */
TEST_IMPL(pipe_getsockname_long_path) {
#ifdef SOCK_MAXADDRLEN
char path[SOCK_MAXADDRLEN - offsetof(struct sockaddr_un, sun_path) + 1];
char name[SOCK_MAXADDRLEN - offsetof(struct sockaddr_un, sun_path) + 1];
uv_pipe_t server;
uv_pipe_t client;
uv_connect_t req;
size_t len;
memset(path, 'x', sizeof(path) - 1);
path[sizeof(path) - 1] = '\0';
unlink(path);
ASSERT_EQ(0, uv_pipe_init(uv_default_loop(), &server, 0));
ASSERT_EQ(0, uv_pipe_init(uv_default_loop(), &client, 0));
ASSERT_EQ(0, uv_pipe_bind(&server, path));
ASSERT_EQ(0, uv_listen((uv_stream_t*) &server, 0, (uv_connection_cb) abort));
uv_pipe_connect(&req, &client, path, long_path_connect_cb);
len = sizeof(name);
ASSERT_EQ(0, uv_pipe_getsockname(&server, name, &len));
ASSERT_EQ(len, sizeof(path) - 1);
ASSERT_MEM_EQ(path, name, len);
uv_close((uv_handle_t*) &server, NULL);
ASSERT_EQ(0, uv_run(uv_default_loop(), UV_RUN_DEFAULT));
unlink(path);
MAKE_VALGRIND_HAPPY();
return 0;
#else
(void) &long_path_connect_cb;
RETURN_SKIP("no long unix path support on this platform");
#endif
}