[glib] Fix various strict aliasing problems with sockaddr



commit d8fe926ba4e799f7b1bd6b0b4464920443bedea9
Author: Philip Withnall <withnall endlessm com>
Date:   Thu Dec 21 17:46:24 2017 +0000

    Fix various strict aliasing problems with sockaddr
    
    Fix various strict aliasing problems caused by casting between (struct
    sockaddr *) and (struct sockaddr_storage *): the correct code here is to
    keep the two in a union.
    
    Signed-off-by: Philip Withnall <withnall endlessm com>
    
    https://bugzilla.gnome.org/show_bug.cgi?id=791622

 gio/gnativesocketaddress.c |    9 +++++--
 gio/gsocket.c              |   51 ++++++++++++++++++++++++++++---------------
 glib/gmessages.c           |   13 +++++++----
 3 files changed, 47 insertions(+), 26 deletions(-)
---
diff --git a/gio/gnativesocketaddress.c b/gio/gnativesocketaddress.c
index 60d81e6..2110634 100644
--- a/gio/gnativesocketaddress.c
+++ b/gio/gnativesocketaddress.c
@@ -47,7 +47,10 @@
 struct _GNativeSocketAddressPrivate
 {
   struct sockaddr *sockaddr;
-  struct sockaddr_storage storage;
+  union {
+    struct sockaddr_storage storage;
+    struct sockaddr sa;
+  } storage;
   gsize sockaddr_len;
 };
 
@@ -58,7 +61,7 @@ g_native_socket_address_dispose (GObject *object)
 {
   GNativeSocketAddress *address = G_NATIVE_SOCKET_ADDRESS (object);
 
-  if (address->priv->sockaddr != (struct sockaddr *)&address->priv->storage)
+  if (address->priv->sockaddr != &address->priv->storage.sa)
     g_free (address->priv->sockaddr);
 
   G_OBJECT_CLASS (g_native_socket_address_parent_class)->dispose (object);
@@ -150,7 +153,7 @@ g_native_socket_address_new (gpointer        native,
   addr = g_object_new (G_TYPE_NATIVE_SOCKET_ADDRESS, NULL);
 
   if (len <= sizeof(addr->priv->storage))
-    addr->priv->sockaddr = (struct sockaddr*)&addr->priv->storage;
+    addr->priv->sockaddr = &addr->priv->storage.sa;
   else
     addr->priv->sockaddr = g_malloc (len);
 
diff --git a/gio/gsocket.c b/gio/gsocket.c
index 567b480..06042d8 100644
--- a/gio/gsocket.c
+++ b/gio/gsocket.c
@@ -421,7 +421,10 @@ check_timeout (GSocket *socket,
 static void
 g_socket_details_from_fd (GSocket *socket)
 {
-  struct sockaddr_storage address;
+  union {
+    struct sockaddr_storage storage;
+    struct sockaddr sa;
+  } address;
   gint fd;
   guint addrlen;
   int value, family;
@@ -454,7 +457,7 @@ g_socket_details_from_fd (GSocket *socket)
     }
 
   addrlen = sizeof address;
-  if (getsockname (fd, (struct sockaddr *) &address, &addrlen) != 0)
+  if (getsockname (fd, &address.sa, &addrlen) != 0)
     {
       errsv = get_socket_errno ();
       goto err;
@@ -463,8 +466,8 @@ g_socket_details_from_fd (GSocket *socket)
   if (addrlen > 0)
     {
       g_assert (G_STRUCT_OFFSET (struct sockaddr, sa_family) +
-               sizeof address.ss_family <= addrlen);
-      family = address.ss_family;
+               sizeof address.storage.ss_family <= addrlen);
+      family = address.storage.ss_family;
     }
   else
     {
@@ -488,7 +491,7 @@ g_socket_details_from_fd (GSocket *socket)
     {
      case G_SOCKET_FAMILY_IPV4:
      case G_SOCKET_FAMILY_IPV6:
-       socket->priv->family = address.ss_family;
+       socket->priv->family = address.storage.ss_family;
        switch (socket->priv->type)
         {
         case G_SOCKET_TYPE_STREAM:
@@ -521,7 +524,7 @@ g_socket_details_from_fd (GSocket *socket)
   if (socket->priv->family != G_SOCKET_FAMILY_INVALID)
     {
       addrlen = sizeof address;
-      if (getpeername (fd, (struct sockaddr *) &address, &addrlen) >= 0)
+      if (getpeername (fd, &address.sa, &addrlen) >= 0)
         {
           socket->priv->connected_read = TRUE;
           socket->priv->connected_write = TRUE;
@@ -1936,12 +1939,15 @@ GSocketAddress *
 g_socket_get_local_address (GSocket  *socket,
                            GError  **error)
 {
-  struct sockaddr_storage buffer;
+  union {
+    struct sockaddr_storage storage;
+    struct sockaddr sa;
+  } buffer;
   guint len = sizeof (buffer);
 
   g_return_val_if_fail (G_IS_SOCKET (socket), NULL);
 
-  if (getsockname (socket->priv->fd, (struct sockaddr *) &buffer, &len) < 0)
+  if (getsockname (socket->priv->fd, &buffer.sa, &len) < 0)
     {
       int errsv = get_socket_errno ();
       g_set_error (error, G_IO_ERROR, socket_io_error_from_errno (errsv),
@@ -1949,7 +1955,7 @@ g_socket_get_local_address (GSocket  *socket,
       return NULL;
     }
 
-  return g_socket_address_new_from_native (&buffer, len);
+  return g_socket_address_new_from_native (&buffer.storage, len);
 }
 
 /**
@@ -1969,7 +1975,10 @@ GSocketAddress *
 g_socket_get_remote_address (GSocket  *socket,
                             GError  **error)
 {
-  struct sockaddr_storage buffer;
+  union {
+    struct sockaddr_storage storage;
+    struct sockaddr sa;
+  } buffer;
   guint len = sizeof (buffer);
 
   g_return_val_if_fail (G_IS_SOCKET (socket), NULL);
@@ -1984,7 +1993,7 @@ g_socket_get_remote_address (GSocket  *socket,
 
   if (!socket->priv->remote_address)
     {
-      if (getpeername (socket->priv->fd, (struct sockaddr *) &buffer, &len) < 0)
+      if (getpeername (socket->priv->fd, &buffer.sa, &len) < 0)
        {
          int errsv = get_socket_errno ();
          g_set_error (error, G_IO_ERROR, socket_io_error_from_errno (errsv),
@@ -1992,7 +2001,7 @@ g_socket_get_remote_address (GSocket  *socket,
          return NULL;
        }
 
-      socket->priv->remote_address = g_socket_address_new_from_native (&buffer, len);
+      socket->priv->remote_address = g_socket_address_new_from_native (&buffer.storage, len);
     }
 
   return g_object_ref (socket->priv->remote_address);
@@ -2104,7 +2113,10 @@ g_socket_bind (GSocket         *socket,
               gboolean         reuse_address,
               GError         **error)
 {
-  struct sockaddr_storage addr;
+  union {
+    struct sockaddr_storage storage;
+    struct sockaddr sa;
+  } addr;
   gboolean so_reuseaddr;
 #ifdef SO_REUSEPORT
   gboolean so_reuseport;
@@ -2115,7 +2127,7 @@ g_socket_bind (GSocket         *socket,
   if (!check_socket (socket, error))
     return FALSE;
 
-  if (!g_socket_address_to_native (address, &addr, sizeof addr, error))
+  if (!g_socket_address_to_native (address, &addr.storage, sizeof addr, error))
     return FALSE;
 
   /* On Windows, SO_REUSEADDR has the semantics we want for UDP
@@ -2147,7 +2159,7 @@ g_socket_bind (GSocket         *socket,
   g_socket_set_option (socket, SOL_SOCKET, SO_REUSEPORT, so_reuseport, NULL);
 #endif
 
-  if (bind (socket->priv->fd, (struct sockaddr *) &addr,
+  if (bind (socket->priv->fd, &addr.sa,
            g_socket_address_get_native_size (address)) < 0)
     {
       int errsv = get_socket_errno ();
@@ -2793,14 +2805,17 @@ g_socket_connect (GSocket         *socket,
                  GCancellable    *cancellable,
                  GError         **error)
 {
-  struct sockaddr_storage buffer;
+  union {
+    struct sockaddr_storage storage;
+    struct sockaddr sa;
+  } buffer;
 
   g_return_val_if_fail (G_IS_SOCKET (socket) && G_IS_SOCKET_ADDRESS (address), FALSE);
 
   if (!check_socket (socket, error))
     return FALSE;
 
-  if (!g_socket_address_to_native (address, &buffer, sizeof buffer, error))
+  if (!g_socket_address_to_native (address, &buffer.storage, sizeof buffer, error))
     return FALSE;
 
   if (socket->priv->remote_address)
@@ -2811,7 +2826,7 @@ g_socket_connect (GSocket         *socket,
     {
       win32_unset_event_mask (socket, FD_CONNECT);
 
-      if (connect (socket->priv->fd, (struct sockaddr *) &buffer,
+      if (connect (socket->priv->fd, &buffer.sa,
                   g_socket_address_get_native_size (address)) < 0)
        {
          int errsv = get_socket_errno ();
diff --git a/glib/gmessages.c b/glib/gmessages.c
index cb2abd5..8c78568 100644
--- a/glib/gmessages.c
+++ b/glib/gmessages.c
@@ -2167,12 +2167,15 @@ g_log_writer_is_journald (gint output_fd)
 
   if (g_once_init_enter (&initialized))
     {
-      struct sockaddr_storage addr;
+      union {
+        struct sockaddr_storage storage;
+        struct sockaddr sa;
+        struct sockaddr_un un;
+      } addr;
       socklen_t addr_len = sizeof(addr);
-      int err = getpeername (output_fd, (struct sockaddr *) &addr, &addr_len);
-      if (err == 0 && addr.ss_family == AF_UNIX)
-        fd_is_journal = g_str_has_prefix (((struct sockaddr_un *)&addr)->sun_path,
-                                          "/run/systemd/journal/");
+      int err = getpeername (output_fd, &addr.sa, &addr_len);
+      if (err == 0 && addr.storage.ss_family == AF_UNIX)
+        fd_is_journal = g_str_has_prefix (addr.un.sun_path, "/run/systemd/journal/");
 
       g_once_init_leave (&initialized, TRUE);
     }


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