diff options
author | Philip Withnall <philip.withnall@collabora.co.uk> | 2013-12-17 09:27:58 +0000 |
---|---|---|
committer | Olivier Crête <olivier.crete@collabora.com> | 2013-12-18 17:50:33 -0500 |
commit | 63e74d8efac70b92df008da8a27d72720216b937 (patch) | |
tree | 13301091104a90abce05445ee582f6419882d30d /socket/udp-bsd.c | |
parent | 71fa5bb8716ea311fc3a1d9cc845a123eb8cd4cc (diff) | |
download | libnice-63e74d8efac70b92df008da8a27d72720216b937.tar.gz |
Fix strict aliasing of sockaddr structures
Casting from one struct sockaddr type to another breaks C’s strict
aliasing rules (variables of different types cannot alias). Fix this
cleanly by using unions of struct sockaddrs to convert between the
types (i.e. type-punning).
I wish sockaddr didn’t have to be this painful.
See:
http://gcc.gnu.org/onlinedocs/gcc-4.4.1/gcc/Optimize-Options.html#Type_002dpunning
Diffstat (limited to 'socket/udp-bsd.c')
-rw-r--r-- | socket/udp-bsd.c | 45 |
1 files changed, 27 insertions, 18 deletions
diff --git a/socket/udp-bsd.c b/socket/udp-bsd.c index 553f0fe..721da00 100644 --- a/socket/udp-bsd.c +++ b/socket/udp-bsd.c @@ -72,7 +72,10 @@ struct UdpBsdSocketPrivate NiceSocket * nice_udp_bsd_socket_new (NiceAddress *addr) { - struct sockaddr_storage name; + union { + struct sockaddr_storage storage; + struct sockaddr addr; + } name; NiceSocket *sock = g_slice_new0 (NiceSocket); GSocket *gsock = NULL; gboolean gret = FALSE; @@ -80,25 +83,25 @@ nice_udp_bsd_socket_new (NiceAddress *addr) struct UdpBsdSocketPrivate *priv; if (addr != NULL) { - nice_address_copy_to_sockaddr(addr, (struct sockaddr *)&name); + nice_address_copy_to_sockaddr(addr, &name.addr); } else { memset (&name, 0, sizeof (name)); - name.ss_family = AF_UNSPEC; + name.storage.ss_family = AF_UNSPEC; } - if (name.ss_family == AF_UNSPEC || name.ss_family == AF_INET) { + if (name.storage.ss_family == AF_UNSPEC || name.storage.ss_family == AF_INET) { gsock = g_socket_new (G_SOCKET_FAMILY_IPV4, G_SOCKET_TYPE_DATAGRAM, G_SOCKET_PROTOCOL_UDP, NULL); - name.ss_family = AF_INET; + name.storage.ss_family = AF_INET; #ifdef HAVE_SA_LEN - name.ss_len = sizeof (struct sockaddr_in); + name.storage.ss_len = sizeof (struct sockaddr_in); #endif - } else if (name.ss_family == AF_INET6) { + } else if (name.storage.ss_family == AF_INET6) { gsock = g_socket_new (G_SOCKET_FAMILY_IPV6, G_SOCKET_TYPE_DATAGRAM, G_SOCKET_PROTOCOL_UDP, NULL); - name.ss_family = AF_INET6; + name.storage.ss_family = AF_INET6; #ifdef HAVE_SA_LEN - name.ss_len = sizeof (struct sockaddr_in6); + name.storage.ss_len = sizeof (struct sockaddr_in6); #endif } @@ -109,7 +112,7 @@ nice_udp_bsd_socket_new (NiceAddress *addr) /* GSocket: All socket file descriptors are set to be close-on-exec. */ g_socket_set_blocking (gsock, false); - gaddr = g_socket_address_new_from_native (&name, sizeof (name)); + gaddr = g_socket_address_new_from_native (&name.addr, sizeof (name)); if (gaddr != NULL) { gret = g_socket_bind (gsock, gaddr, FALSE, NULL); g_object_unref (gaddr); @@ -124,7 +127,7 @@ nice_udp_bsd_socket_new (NiceAddress *addr) gaddr = g_socket_get_local_address (gsock, NULL); if (gaddr == NULL || - !g_socket_address_to_native (gaddr, &name, sizeof(name), NULL)) { + !g_socket_address_to_native (gaddr, &name.addr, sizeof(name), NULL)) { g_slice_free (NiceSocket, sock); g_socket_close (gsock, NULL); g_object_unref (gsock); @@ -133,7 +136,7 @@ nice_udp_bsd_socket_new (NiceAddress *addr) g_object_unref (gaddr); - nice_address_set_from_sockaddr (&sock->addr, (struct sockaddr *)&name); + nice_address_set_from_sockaddr (&sock->addr, &name.addr); priv = sock->priv = g_slice_new0 (struct UdpBsdSocketPrivate); nice_address_init (&priv->niceaddr); @@ -181,10 +184,13 @@ socket_recv (NiceSocket *sock, NiceAddress *from, guint len, gchar *buf) } if (recvd > 0 && from != NULL && gaddr != NULL) { - struct sockaddr_storage sa; + union { + struct sockaddr_storage storage; + struct sockaddr addr; + } sa; - g_socket_address_to_native (gaddr, &sa, sizeof (sa), NULL); - nice_address_set_from_sockaddr (from, (struct sockaddr *)&sa); + g_socket_address_to_native (gaddr, &sa.addr, sizeof (sa), NULL); + nice_address_set_from_sockaddr (from, &sa.addr); } if (gaddr != NULL) @@ -202,13 +208,16 @@ socket_send (NiceSocket *sock, const NiceAddress *to, if (!nice_address_is_valid (&priv->niceaddr) || !nice_address_equal (&priv->niceaddr, to)) { - struct sockaddr_storage sa; + union { + struct sockaddr_storage storage; + struct sockaddr addr; + } sa; GSocketAddress *gaddr; if (priv->gaddr) g_object_unref (priv->gaddr); - nice_address_copy_to_sockaddr (to, (struct sockaddr *)&sa); - gaddr = g_socket_address_new_from_native (&sa, sizeof(sa)); + nice_address_copy_to_sockaddr (to, &sa.addr); + gaddr = g_socket_address_new_from_native (&sa.addr, sizeof(sa)); if (gaddr == NULL) return -1; priv->gaddr = gaddr; |