1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-01-10 01:48:00 +00:00

Avoid "dereferencing pointer 'sa' does break strict-aliasing rules" warnings

from recent versions of GCC.

[originally from svn r8612]
This commit is contained in:
Jacob Nevins 2009-08-06 22:12:05 +00:00
parent 0abd192e83
commit 16eeab4066

View File

@ -31,6 +31,20 @@
# define X11_UNIX_PATH "/tmp/.X11-unix/X" # define X11_UNIX_PATH "/tmp/.X11-unix/X"
#endif #endif
/*
* Access to sockaddr types without breaking C strict aliasing rules.
*/
union sockaddr_union {
#ifdef NO_IPV6
struct sockaddr_in storage;
#else
struct sockaddr_storage storage;
struct sockaddr_in6 sin6;
#endif
struct sockaddr sa;
struct sockaddr_in sin;
};
/* /*
* We used to typedef struct Socket_tag *Socket. * We used to typedef struct Socket_tag *Socket.
* *
@ -338,19 +352,13 @@ int sk_hostname_is_local(char *name)
static int sockaddr_is_loopback(struct sockaddr *sa) static int sockaddr_is_loopback(struct sockaddr *sa)
{ {
struct sockaddr_in *sin; union sockaddr_union *u = (union sockaddr_union *)sa;
#ifndef NO_IPV6 switch (u->sa.sa_family) {
struct sockaddr_in6 *sin6;
#endif
switch (sa->sa_family) {
case AF_INET: case AF_INET:
sin = (struct sockaddr_in *)sa; return ipv4_is_loopback(u->sin.sin_addr);
return ipv4_is_loopback(sin->sin_addr);
#ifndef NO_IPV6 #ifndef NO_IPV6
case AF_INET6: case AF_INET6:
sin6 = (struct sockaddr_in6 *)sa; return IN6_IS_ADDR_LOOPBACK(&u->sin6.sin6_addr);
return IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr);
#endif #endif
case AF_UNIX: case AF_UNIX:
return TRUE; return TRUE;
@ -949,14 +957,7 @@ static void sk_tcp_close(Socket sock)
void *sk_getxdmdata(void *sock, int *lenp) void *sk_getxdmdata(void *sock, int *lenp)
{ {
Actual_Socket s = (Actual_Socket) sock; Actual_Socket s = (Actual_Socket) sock;
#ifdef NO_IPV6 union sockaddr_union u;
struct sockaddr_in addr;
#else
struct sockaddr_storage addr;
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&addr;
#endif
struct sockaddr *sa = (struct sockaddr *)&addr;
struct sockaddr_in *sin = (struct sockaddr_in *)&addr;
socklen_t addrlen; socklen_t addrlen;
char *buf; char *buf;
static unsigned int unix_addr = 0xFFFFFFFF; static unsigned int unix_addr = 0xFFFFFFFF;
@ -967,23 +968,23 @@ void *sk_getxdmdata(void *sock, int *lenp)
if (s->fn != &tcp_fn_table) if (s->fn != &tcp_fn_table)
return NULL; /* failure */ return NULL; /* failure */
addrlen = sizeof(addr); addrlen = sizeof(u);
if (getsockname(s->s, sa, &addrlen) < 0) if (getsockname(s->s, &u.sa, &addrlen) < 0)
return NULL; return NULL;
switch(sa->sa_family) { switch(u.sa.sa_family) {
case AF_INET: case AF_INET:
*lenp = 6; *lenp = 6;
buf = snewn(*lenp, char); buf = snewn(*lenp, char);
PUT_32BIT_MSB_FIRST(buf, ntohl(sin->sin_addr.s_addr)); PUT_32BIT_MSB_FIRST(buf, ntohl(u.sin.sin_addr.s_addr));
PUT_16BIT_MSB_FIRST(buf+4, ntohs(sin->sin_port)); PUT_16BIT_MSB_FIRST(buf+4, ntohs(u.sin.sin_port));
break; break;
#ifndef NO_IPV6 #ifndef NO_IPV6
case AF_INET6: case AF_INET6:
*lenp = 6; *lenp = 6;
buf = snewn(*lenp, char); buf = snewn(*lenp, char);
if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) { if (IN6_IS_ADDR_V4MAPPED(&u.sin6.sin6_addr)) {
memcpy(buf, sin6->sin6_addr.s6_addr + 12, 4); memcpy(buf, u.sin6.sin6_addr.s6_addr + 12, 4);
PUT_16BIT_MSB_FIRST(buf+4, ntohs(sin6->sin6_port)); PUT_16BIT_MSB_FIRST(buf+4, ntohs(u.sin6.sin6_port));
} else } else
/* This is stupid, but it's what XLib does. */ /* This is stupid, but it's what XLib does. */
memset(buf, 0, 6); memset(buf, 0, 6);