From 5773470ff3a85640fbaeab1a88edc3fa395184bd Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Thu, 22 Nov 2018 09:21:22 -0800 Subject: [PATCH] emacsclient: sockaddr portability fixes MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit * lib-src/emacsclient.c (get_server_config, set_tcp_socket) (set_local_socket): Initialize any platform-specific extensions of struct to zero, just in case. (set_tcp_socket, set_local_socket): Don’t assume struct layout details that POSIX does not specify. Use union to sidestep some problems with strict aliasing. Remove unnecessary casts. --- lib-src/emacsclient.c | 46 +++++++++++++++++++++++-------------------- 1 file changed, 25 insertions(+), 21 deletions(-) diff --git a/lib-src/emacsclient.c b/lib-src/emacsclient.c index 4ab97c3c50c..e6eb3c74cf7 100644 --- a/lib-src/emacsclient.c +++ b/lib-src/emacsclient.c @@ -959,6 +959,7 @@ get_server_config (const char *config_file, struct sockaddr_in *server, exit (EXIT_FAILURE); } + memset (server, 0, sizeof *server); server->sin_family = AF_INET; server->sin_addr.s_addr = inet_addr (dotted); server->sin_port = htons (atoi (port)); @@ -977,16 +978,19 @@ get_server_config (const char *config_file, struct sockaddr_in *server, static HSOCKET set_tcp_socket (const char *local_server_file) { - struct sockaddr_in server; - struct linger l_arg = {1, 1}; + union { + struct sockaddr_in in; + struct sockaddr sa; + } server; + struct linger l_arg = { .l_onoff = 1, .l_linger = 1 }; char auth_string[AUTH_KEY_LENGTH + 1]; - if (! get_server_config (local_server_file, &server, auth_string)) + if (! get_server_config (local_server_file, &server.in, auth_string)) return INVALID_SOCKET; - if (server.sin_addr.s_addr != inet_addr ("127.0.0.1") && !quiet) + if (server.in.sin_addr.s_addr != inet_addr ("127.0.0.1") && !quiet) message (false, "%s: connected to remote socket at %s\n", - progname, inet_ntoa (server.sin_addr)); + progname, inet_ntoa (server.in.sin_addr)); /* Open up an AF_INET socket. */ HSOCKET s = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP); @@ -1004,7 +1008,7 @@ set_tcp_socket (const char *local_server_file) } /* Set up the socket. */ - if (connect (s, (struct sockaddr *) &server, sizeof server) < 0) + if (connect (s, &server.sa, sizeof server.in) != 0) { # ifdef WINDOWSNT if(!(w32_window_app () && alternate_editor)) @@ -1013,7 +1017,7 @@ set_tcp_socket (const char *local_server_file) return INVALID_SOCKET; } - setsockopt (s, SOL_SOCKET, SO_LINGER, (char *) &l_arg, sizeof l_arg); + setsockopt (s, SOL_SOCKET, SO_LINGER, &l_arg, sizeof l_arg); /* Send the authentication. */ auth_string[AUTH_KEY_LENGTH] = '\0'; @@ -1183,13 +1187,16 @@ init_signals (void) signal (SIGTTOU, handle_sigtstp); } +/* Create a local socket and connect it to Emacs. */ static HSOCKET set_local_socket (const char *local_socket_name) { - struct sockaddr_un server; + union { + struct sockaddr_un un; + struct sockaddr sa; + } server = {{ .sun_family = AF_UNIX }}; - /* Open up an AF_UNIX socket in this person's home directory. */ HSOCKET s = socket (AF_UNIX, SOCK_STREAM, 0); if (s < 0) { @@ -1197,8 +1204,6 @@ set_local_socket (const char *local_socket_name) return INVALID_SOCKET; } - server.sun_family = AF_UNIX; - int sock_status; int saved_errno; char const *server_name = local_socket_name; @@ -1221,7 +1226,7 @@ set_local_socket (const char *local_socket_name) # ifndef _CS_DARWIN_USER_TEMP_DIR # define _CS_DARWIN_USER_TEMP_DIR 65537 # endif - size_t n = confstr (_CS_DARWIN_USER_TEMP_DIR, NULL, (size_t) 0); + size_t n = confstr (_CS_DARWIN_USER_TEMP_DIR, NULL, 0); if (n > 0) { tmpdir = tmpdir_storage = xmalloc (n); @@ -1238,8 +1243,8 @@ set_local_socket (const char *local_socket_name) local_socket_name = socket_name_storage; } - if (strlen (local_socket_name) < sizeof (server.sun_path)) - strcpy (server.sun_path, local_socket_name); + if (strlen (local_socket_name) < sizeof server.un.sun_path) + strcpy (server.un.sun_path, local_socket_name); else { message (true, "%s: socket-name %s too long\n", @@ -1248,7 +1253,7 @@ set_local_socket (const char *local_socket_name) } /* See if the socket exists, and if it's owned by us. */ - sock_status = socket_status (server.sun_path); + sock_status = socket_status (server.un.sun_path); saved_errno = errno; if (sock_status && tmpdir) { @@ -1276,8 +1281,8 @@ set_local_socket (const char *local_socket_name) char *z = stpcpy (user_socket_name, tmpdir); strcpy (z + sprintf (z, subdir_format, uid), server_name); - if (strlen (user_socket_name) < sizeof (server.sun_path)) - strcpy (server.sun_path, user_socket_name); + if (strlen (user_socket_name) < sizeof server.un.sun_path) + strcpy (server.un.sun_path, user_socket_name); else { message (true, "%s: socket-name %s too long\n", @@ -1286,7 +1291,7 @@ set_local_socket (const char *local_socket_name) } free (user_socket_name); - sock_status = socket_status (server.sun_path); + sock_status = socket_status (server.un.sun_path); saved_errno = errno; } else @@ -1314,12 +1319,11 @@ set_local_socket (const char *local_socket_name) progname, progname); else message (true, "%s: can't stat %s: %s\n", - progname, server.sun_path, strerror (saved_errno)); + progname, server.un.sun_path, strerror (sock_status)); return INVALID_SOCKET; } - if (connect (s, (struct sockaddr *) &server, strlen (server.sun_path) + 2) - < 0) + if (connect (s, &server.sa, sizeof server.un) != 0) { message (true, "%s: connect: %s\n", progname, strerror (errno)); return INVALID_SOCKET; -- 2.39.2