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 /agent/address.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 'agent/address.c')
-rw-r--r-- | agent/address.c | 17 |
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 (); |