From c2c6c3c8c66855d9ccbe079015355ae8db8ff5e5 Mon Sep 17 00:00:00 2001 From: Kaz Kylheku Date: Thu, 31 Mar 2016 21:33:32 -0700 Subject: Bugfix: support abstract UNIX socket addresses on Linux. Making it work as already documented. * socket.c (MIN): New macro. (sockaddr_pack): Use utf8_dup_to_buf to convert Unix socket path to a buffer of UTF-8 bytes, possibly with one or more embedded null bytes. Copy as much of this as fits into the sun_path member of struct sockaddr_un. * txr.1: Improve documentation about the abstract names on Linux. --- socket.c | 7 +++++-- txr.1 | 38 ++++++++++++++++++++++++++++++++++---- 2 files changed, 39 insertions(+), 6 deletions(-) diff --git a/socket.c b/socket.c index 39c4d931..e90d374e 100644 --- a/socket.c +++ b/socket.c @@ -51,6 +51,8 @@ #include "arith.h" #include "socket.h" +#define MIN(A, B) ((A) < (B) ? (A) : (B)) + struct dgram_stream { struct strm_base a; val stream; @@ -244,11 +246,12 @@ static void sockaddr_pack(val sockaddr, val family, *len = sizeof *sa; } else if (addr_type == sockaddr_un_s) { val path = slot(sockaddr, path_s); - char *path_u8 = utf8_dup_to(c_str(path)); struct sockaddr_un *sa = coerce(struct sockaddr_un *, buf); + size_t size; + unsigned char *path_u8 = utf8_dup_to_buf(c_str(path), &size, 0); memset(sa, 0, sizeof *sa); sa->sun_family = AF_UNIX; - strncpy(sa->sun_path, path_u8, sizeof sa->sun_path - 1); + memcpy(sa->sun_path, path_u8, MIN(size, sizeof sa->sun_path)); free(path_u8); *len = sizeof *sa; } else { diff --git a/txr.1 b/txr.1 index c2f9e06d..01cd4ea6 100644 --- a/txr.1 +++ b/txr.1 @@ -37932,10 +37932,40 @@ address family. This structure has only one slot, .code path which holds the rendezvous name for connecting pairs of socket endpoints. -This names appears in the filesystem. Linux systems have support for "abstract" -names which do not appear in the filesystem. These abstract names are distinguished -by starting with a null byte. In \*(TX, a null byte can be encoded in a string -using the pseudo-null code point U+DC00. +This name appears in the filesystem. + +When the +.code sockaddr-un +structure is converted to the C structure +.code "struct sockaddr_un" , +the +.code path +slot undergoes conversion to UTF-8. The resulting bytes are stored in the +.code sun_path +member of the C structure. If the resulting UTF-8 byte string +is larger than the +.code sun_path +array, it is silently truncated. + +Note: Linux systems have support for "abstract" names which do not appear in +the filesystem. These abstract names are distinguished by starting with a null +byte. For more information, consult Linux documentation. +This convention is supported in the +.code path +slot of the +.code sockaddr-un +structure. If +.code path +contains occurrences of the pseudo-null character U+DC00, these translate +to null bytes in the +.code sun_path +member of the corresponding C structure +.codn "struct sockaddr_un" . +For example, the path +.str "\exDC00;foo" +is valid and represents an abstract address consisting of the three bytes +.str "foo" +followed by null padding bytes. .coNP Structure @ addrinfo .synb -- cgit v1.2.3