emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Emacs-diffs] master e54a3b4: Avoid undefined behavior in struct sockadd


From: Paul Eggert
Subject: [Emacs-diffs] master e54a3b4: Avoid undefined behavior in struct sockaddr
Date: Wed, 17 May 2017 16:37:02 -0400 (EDT)

branch: master
commit e54a3b4fde0c3de7964a2e604c7381101e5d9951
Author: Paul Eggert <address@hidden>
Commit: Paul Eggert <address@hidden>

    Avoid undefined behavior in struct sockaddr
    
    Problem noted by Philipp Stephani in:
    http://lists.gnu.org/archive/html/emacs-devel/2017-05/msg00391.html
    * src/conf_post.h (ATTRIBUTE_MAY_ALIAS, DECLARE_POINTER_ALIAS):
    New macros.
    * src/process.c (conv_sockaddr_to_lisp, conv_lisp_to_sockaddr)
    (connect_network_socket, network_interface_info)
    (server_accept_connection): Use it when aliasing non-char objects.
---
 src/conf_post.h | 14 ++++++++++++++
 src/process.c   | 31 +++++++++++++++++--------------
 2 files changed, 31 insertions(+), 14 deletions(-)

diff --git a/src/conf_post.h b/src/conf_post.h
index 1462bd1..c05c93b 100644
--- a/src/conf_post.h
+++ b/src/conf_post.h
@@ -263,6 +263,20 @@ extern int emacs_setenv_TZ (char const *);
 #define ATTRIBUTE_CONST _GL_ATTRIBUTE_CONST
 #define ATTRIBUTE_UNUSED _GL_UNUSED
 
+#if GNUC_PREREQ (3, 3, 0)
+# define ATTRIBUTE_MAY_ALIAS __attribute__ ((__may_alias__))
+#else
+# define ATTRIBUTE_MAY_ALIAS
+#endif
+
+/* Declare NAME to be a pointer to an object of type TYPE, initialized
+   to the address ADDR, which may be of a different type.  Accesses
+   via NAME may alias with other accesses with the traditional
+   behavior, even if options like gcc -fstrict-aliasing are used.  */
+
+#define DECLARE_POINTER_ALIAS(name, type, addr) \
+  type ATTRIBUTE_MAY_ALIAS *name = (type *) (addr)
+
 #if 3 <= __GNUC__
 # define ATTRIBUTE_MALLOC __attribute__ ((__malloc__))
 #else
diff --git a/src/process.c b/src/process.c
index 8180fea..c301739 100644
--- a/src/process.c
+++ b/src/process.c
@@ -2476,7 +2476,7 @@ conv_sockaddr_to_lisp (struct sockaddr *sa, ptrdiff_t len)
     {
     case AF_INET:
       {
-       struct sockaddr_in *sin = (struct sockaddr_in *) sa;
+       DECLARE_POINTER_ALIAS (sin, struct sockaddr_in, sa);
        len = sizeof (sin->sin_addr) + 1;
        address = Fmake_vector (make_number (len), Qnil);
        p = XVECTOR (address);
@@ -2487,8 +2487,8 @@ conv_sockaddr_to_lisp (struct sockaddr *sa, ptrdiff_t len)
 #ifdef AF_INET6
     case AF_INET6:
       {
-       struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) sa;
-       uint16_t *ip6 = (uint16_t *) &sin6->sin6_addr;
+       DECLARE_POINTER_ALIAS (sin6, struct sockaddr_in6, sa);
+       DECLARE_POINTER_ALIAS (ip6, uint16_t, &sin6->sin6_addr);
        len = sizeof (sin6->sin6_addr) / 2 + 1;
        address = Fmake_vector (make_number (len), Qnil);
        p = XVECTOR (address);
@@ -2501,7 +2501,7 @@ conv_sockaddr_to_lisp (struct sockaddr *sa, ptrdiff_t len)
 #ifdef HAVE_LOCAL_SOCKETS
     case AF_LOCAL:
       {
-       struct sockaddr_un *sockun = (struct sockaddr_un *) sa;
+       DECLARE_POINTER_ALIAS (sockun, struct sockaddr_un, sa);
         ptrdiff_t name_length = len - offsetof (struct sockaddr_un, sun_path);
         /* If the first byte is NUL, the name is a Linux abstract
            socket name, and the name can contain embedded NULs.  If
@@ -2612,7 +2612,7 @@ conv_lisp_to_sockaddr (int family, Lisp_Object address, 
struct sockaddr *sa, int
       p = XVECTOR (address);
       if (family == AF_INET)
        {
-         struct sockaddr_in *sin = (struct sockaddr_in *) sa;
+         DECLARE_POINTER_ALIAS (sin, struct sockaddr_in, sa);
          len = sizeof (sin->sin_addr) + 1;
          hostport = XINT (p->contents[--len]);
          sin->sin_port = htons (hostport);
@@ -2622,8 +2622,8 @@ conv_lisp_to_sockaddr (int family, Lisp_Object address, 
struct sockaddr *sa, int
 #ifdef AF_INET6
       else if (family == AF_INET6)
        {
-         struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) sa;
-         uint16_t *ip6 = (uint16_t *)&sin6->sin6_addr;
+         DECLARE_POINTER_ALIAS (sin6, struct sockaddr_in6, sa);
+         DECLARE_POINTER_ALIAS (ip6, uint16_t, &sin6->sin6_addr);
          len = sizeof (sin6->sin6_addr) / 2 + 1;
          hostport = XINT (p->contents[--len]);
          sin6->sin6_port = htons (hostport);
@@ -2645,7 +2645,7 @@ conv_lisp_to_sockaddr (int family, Lisp_Object address, 
struct sockaddr *sa, int
 #ifdef HAVE_LOCAL_SOCKETS
       if (family == AF_LOCAL)
        {
-         struct sockaddr_un *sockun = (struct sockaddr_un *) sa;
+         DECLARE_POINTER_ALIAS (sockun, struct sockaddr_un, sa);
          cp = SDATA (address);
          for (i = 0; i < sizeof (sockun->sun_path) && *cp; i++)
            sockun->sun_path[i] = *cp++;
@@ -3436,13 +3436,15 @@ connect_network_socket (Lisp_Object proc, Lisp_Object 
addrinfos,
                       == offsetof (struct sockaddr_in6, sin6_port))
                      && sizeof (sa1.sin_port) == sizeof (sa6.sin6_port));
 #endif
-             if (getsockname (s, (struct sockaddr *)&sa1, &len1) == 0)
+             DECLARE_POINTER_ALIAS (psa1, struct sockaddr, &sa1);
+             if (getsockname (s, psa1, &len1) == 0)
                {
                  Lisp_Object service = make_number (ntohs (sa1.sin_port));
                  contact = Fplist_put (contact, QCservice, service);
                  /* Save the port number so that we can stash it in
                     the process object later.  */
-                 ((struct sockaddr_in *) sa)->sin_port = sa1.sin_port;
+                 DECLARE_POINTER_ALIAS (psa, struct sockaddr_in, sa);
+                 psa->sin_port = sa1.sin_port;
                }
            }
 #endif
@@ -3550,9 +3552,10 @@ connect_network_socket (Lisp_Object proc, Lisp_Object 
addrinfos,
        {
          struct sockaddr_storage sa1;
          socklen_t len1 = sizeof (sa1);
-         if (getsockname (s, (struct sockaddr *)&sa1, &len1) == 0)
+         DECLARE_POINTER_ALIAS (psa1, struct sockaddr, &sa1);
+         if (getsockname (s, psa1, &len1) == 0)
            contact = Fplist_put (contact, QClocal,
-                                 conv_sockaddr_to_lisp ((struct sockaddr 
*)&sa1, len1));
+                                 conv_sockaddr_to_lisp (psa1, len1));
        }
 #endif
     }
@@ -4401,7 +4404,7 @@ network_interface_info (Lisp_Object ifname)
 
       for (it = ifap; it != NULL; it = it->ifa_next)
         {
-          struct sockaddr_dl *sdl = (struct sockaddr_dl *) it->ifa_addr;
+         DECLARE_POINTER_ALIAS (sdl, struct sockaddr_dl, it->ifa_addr);
           unsigned char linkaddr[6];
           int n;
 
@@ -4722,7 +4725,7 @@ server_accept_connection (Lisp_Object server, int channel)
       {
        args[nargs++] = procname_format_in6;
        nargs++;
-       uint16_t *ip6 = (uint16_t *)&saddr.in6.sin6_addr;
+       DECLARE_POINTER_ALIAS (ip6, uint16_t, &saddr.in6.sin6_addr);
        service = make_number (ntohs (saddr.in.sin_port));
        for (int i = 0; i < 8; i++)
          args[nargs++] = make_number (ip6[i]);



reply via email to

[Prev in Thread] Current Thread [Next in Thread]