summaryrefslogtreecommitdiff
path: root/agent/address.c
diff options
context:
space:
mode:
authorPhilip Withnall <philip.withnall@collabora.co.uk>2013-12-17 09:27:58 +0000
committerOlivier Crête <olivier.crete@collabora.com>2013-12-18 17:50:33 -0500
commit63e74d8efac70b92df008da8a27d72720216b937 (patch)
tree13301091104a90abce05445ee582f6419882d30d /agent/address.c
parent71fa5bb8716ea311fc3a1d9cc845a123eb8cd4cc (diff)
downloadlibnice-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 'agent/address.c')
-rw-r--r--agent/address.c17
1 files changed, 11 insertions, 6 deletions
diff --git a/agent/address.c b/agent/address.c
index e37744d..9a7fe33 100644
--- a/agent/address.c
+++ b/agent/address.c
@@ -226,20 +226,25 @@ nice_address_set_from_sockaddr (NiceAddress *addr,
NICEAPI_EXPORT void
nice_address_copy_to_sockaddr (const NiceAddress *addr,
- struct sockaddr *sa)
+ struct sockaddr *_sa)
{
- struct sockaddr_in *sin4 = (struct sockaddr_in *)sa;
- struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
+ union {
+ struct sockaddr *addr;
+ struct sockaddr_in *in;
+ struct sockaddr_in6 *in6;
+ } sa;
- g_assert (sa);
+ sa.addr = _sa;
+
+ g_assert (_sa);
switch (addr->s.addr.sa_family)
{
case AF_INET:
- memcpy (sin4, &addr->s.ip4, sizeof (*sin4));
+ memcpy (sa.in, &addr->s.ip4, sizeof (*sa.in));
break;
case AF_INET6:
- memcpy (sin6, &addr->s.ip6, sizeof (*sin6));
+ memcpy (sa.in6, &addr->s.ip6, sizeof (*sa.in6));
break;
default:
g_return_if_reached ();