Well it seems I was wrong and this is a common-or-garden bug. Specifically,
from xauth/gethost.c, starting at line 199:
#ifdef HAVE_STRLCPY
strlcpy(path, fulldpyname, sizeof(path));
#else
strncpy(path, fulldpyname, sizeof(path));
path[sizeof(path) - 1] = '\0';
#endif
if (0 == stat(path, &sbuf)) {
is_path_to_socket = 1;
} else {
char *dot = strrchr(path, '.');
if (dot) {
*dot = '\0';
/* screen = atoi(dot + 1); */
if (0 == stat(path, &sbuf)) {
is_path_to_socket = 1;
}
}
}
fulldpyname is "drogo.datum:0" and there is a directory in $HOME named "drogo".
is_path_to_socket then gets set to 1 and the strlcpy(buf, strrchr(fulldpyname,
'/') + 1, sizeof(buf)) a few lines down passes 0x01 as the source pointer to
strlcpy.
I don't know if it is or should be required that $DISPLAY pointing to a unix
socket can be a relative path, but if they must be absolute then this patch
enforces that (and fixes my segfault, though by making the same assumption that
$DISPLAY will include a '/' in two places).
Matthew
Index: parsedpy.c
===================================================================
RCS file: /home/flask/src/openbsd/cvsync/xenocara/app/xauth/parsedpy.c,v
retrieving revision 1.5
diff -u -p -r1.5 parsedpy.c
--- parsedpy.c 19 Feb 2017 17:30:58 -0000 1.5
+++ parsedpy.c 18 Oct 2019 12:02:34 -0000
@@ -177,7 +177,7 @@ parse_displayname (const char *displayna
#endif
if (0 == stat(path, &sbuf)) {
family = FamilyLocal;
- } else {
+ } else if (strrchr(path, '/') == path) { /* I'm not sure this is the
best way to test for this */
char *dot = strrchr(path, '.');
if (dot) {
*dot = '\0';