aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPaul Eggert2017-05-17 13:35:52 -0700
committerPaul Eggert2017-05-17 13:36:56 -0700
commite54a3b4fde0c3de7964a2e604c7381101e5d9951 (patch)
treed663011b3e5c07c978078a4879f77907d1db3262 /src
parent184d74ce002ecb7399cb2b47fc671bfb2feb9855 (diff)
downloademacs-e54a3b4fde0c3de7964a2e604c7381101e5d9951.tar.gz
emacs-e54a3b4fde0c3de7964a2e604c7381101e5d9951.zip
Avoid undefined behavior in struct sockaddr
Problem noted by Philipp Stephani in: http://lists.gnu.org/archive/html/emacs-devel/2017-05/msg00391.html * src/conf_post.h (ATTRIBUTE_MAY_ALIAS, DECLARE_POINTER_ALIAS): New macros. * src/process.c (conv_sockaddr_to_lisp, conv_lisp_to_sockaddr) (connect_network_socket, network_interface_info) (server_accept_connection): Use it when aliasing non-char objects.
Diffstat (limited to 'src')
-rw-r--r--src/conf_post.h14
-rw-r--r--src/process.c31
2 files changed, 31 insertions, 14 deletions
diff --git a/src/conf_post.h b/src/conf_post.h
index 1462bd16c75..c05c93b8190 100644
--- a/src/conf_post.h
+++ b/src/conf_post.h
@@ -263,6 +263,20 @@ extern int emacs_setenv_TZ (char const *);
263#define ATTRIBUTE_CONST _GL_ATTRIBUTE_CONST 263#define ATTRIBUTE_CONST _GL_ATTRIBUTE_CONST
264#define ATTRIBUTE_UNUSED _GL_UNUSED 264#define ATTRIBUTE_UNUSED _GL_UNUSED
265 265
266#if GNUC_PREREQ (3, 3, 0)
267# define ATTRIBUTE_MAY_ALIAS __attribute__ ((__may_alias__))
268#else
269# define ATTRIBUTE_MAY_ALIAS
270#endif
271
272/* Declare NAME to be a pointer to an object of type TYPE, initialized
273 to the address ADDR, which may be of a different type. Accesses
274 via NAME may alias with other accesses with the traditional
275 behavior, even if options like gcc -fstrict-aliasing are used. */
276
277#define DECLARE_POINTER_ALIAS(name, type, addr) \
278 type ATTRIBUTE_MAY_ALIAS *name = (type *) (addr)
279
266#if 3 <= __GNUC__ 280#if 3 <= __GNUC__
267# define ATTRIBUTE_MALLOC __attribute__ ((__malloc__)) 281# define ATTRIBUTE_MALLOC __attribute__ ((__malloc__))
268#else 282#else
diff --git a/src/process.c b/src/process.c
index 8180feaba9a..c30173955d2 100644
--- a/src/process.c
+++ b/src/process.c
@@ -2476,7 +2476,7 @@ conv_sockaddr_to_lisp (struct sockaddr *sa, ptrdiff_t len)
2476 { 2476 {
2477 case AF_INET: 2477 case AF_INET:
2478 { 2478 {
2479 struct sockaddr_in *sin = (struct sockaddr_in *) sa; 2479 DECLARE_POINTER_ALIAS (sin, struct sockaddr_in, sa);
2480 len = sizeof (sin->sin_addr) + 1; 2480 len = sizeof (sin->sin_addr) + 1;
2481 address = Fmake_vector (make_number (len), Qnil); 2481 address = Fmake_vector (make_number (len), Qnil);
2482 p = XVECTOR (address); 2482 p = XVECTOR (address);
@@ -2487,8 +2487,8 @@ conv_sockaddr_to_lisp (struct sockaddr *sa, ptrdiff_t len)
2487#ifdef AF_INET6 2487#ifdef AF_INET6
2488 case AF_INET6: 2488 case AF_INET6:
2489 { 2489 {
2490 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) sa; 2490 DECLARE_POINTER_ALIAS (sin6, struct sockaddr_in6, sa);
2491 uint16_t *ip6 = (uint16_t *) &sin6->sin6_addr; 2491 DECLARE_POINTER_ALIAS (ip6, uint16_t, &sin6->sin6_addr);
2492 len = sizeof (sin6->sin6_addr) / 2 + 1; 2492 len = sizeof (sin6->sin6_addr) / 2 + 1;
2493 address = Fmake_vector (make_number (len), Qnil); 2493 address = Fmake_vector (make_number (len), Qnil);
2494 p = XVECTOR (address); 2494 p = XVECTOR (address);
@@ -2501,7 +2501,7 @@ conv_sockaddr_to_lisp (struct sockaddr *sa, ptrdiff_t len)
2501#ifdef HAVE_LOCAL_SOCKETS 2501#ifdef HAVE_LOCAL_SOCKETS
2502 case AF_LOCAL: 2502 case AF_LOCAL:
2503 { 2503 {
2504 struct sockaddr_un *sockun = (struct sockaddr_un *) sa; 2504 DECLARE_POINTER_ALIAS (sockun, struct sockaddr_un, sa);
2505 ptrdiff_t name_length = len - offsetof (struct sockaddr_un, sun_path); 2505 ptrdiff_t name_length = len - offsetof (struct sockaddr_un, sun_path);
2506 /* If the first byte is NUL, the name is a Linux abstract 2506 /* If the first byte is NUL, the name is a Linux abstract
2507 socket name, and the name can contain embedded NULs. If 2507 socket name, and the name can contain embedded NULs. If
@@ -2612,7 +2612,7 @@ conv_lisp_to_sockaddr (int family, Lisp_Object address, struct sockaddr *sa, int
2612 p = XVECTOR (address); 2612 p = XVECTOR (address);
2613 if (family == AF_INET) 2613 if (family == AF_INET)
2614 { 2614 {
2615 struct sockaddr_in *sin = (struct sockaddr_in *) sa; 2615 DECLARE_POINTER_ALIAS (sin, struct sockaddr_in, sa);
2616 len = sizeof (sin->sin_addr) + 1; 2616 len = sizeof (sin->sin_addr) + 1;
2617 hostport = XINT (p->contents[--len]); 2617 hostport = XINT (p->contents[--len]);
2618 sin->sin_port = htons (hostport); 2618 sin->sin_port = htons (hostport);
@@ -2622,8 +2622,8 @@ conv_lisp_to_sockaddr (int family, Lisp_Object address, struct sockaddr *sa, int
2622#ifdef AF_INET6 2622#ifdef AF_INET6
2623 else if (family == AF_INET6) 2623 else if (family == AF_INET6)
2624 { 2624 {
2625 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) sa; 2625 DECLARE_POINTER_ALIAS (sin6, struct sockaddr_in6, sa);
2626 uint16_t *ip6 = (uint16_t *)&sin6->sin6_addr; 2626 DECLARE_POINTER_ALIAS (ip6, uint16_t, &sin6->sin6_addr);
2627 len = sizeof (sin6->sin6_addr) / 2 + 1; 2627 len = sizeof (sin6->sin6_addr) / 2 + 1;
2628 hostport = XINT (p->contents[--len]); 2628 hostport = XINT (p->contents[--len]);
2629 sin6->sin6_port = htons (hostport); 2629 sin6->sin6_port = htons (hostport);
@@ -2645,7 +2645,7 @@ conv_lisp_to_sockaddr (int family, Lisp_Object address, struct sockaddr *sa, int
2645#ifdef HAVE_LOCAL_SOCKETS 2645#ifdef HAVE_LOCAL_SOCKETS
2646 if (family == AF_LOCAL) 2646 if (family == AF_LOCAL)
2647 { 2647 {
2648 struct sockaddr_un *sockun = (struct sockaddr_un *) sa; 2648 DECLARE_POINTER_ALIAS (sockun, struct sockaddr_un, sa);
2649 cp = SDATA (address); 2649 cp = SDATA (address);
2650 for (i = 0; i < sizeof (sockun->sun_path) && *cp; i++) 2650 for (i = 0; i < sizeof (sockun->sun_path) && *cp; i++)
2651 sockun->sun_path[i] = *cp++; 2651 sockun->sun_path[i] = *cp++;
@@ -3436,13 +3436,15 @@ connect_network_socket (Lisp_Object proc, Lisp_Object addrinfos,
3436 == offsetof (struct sockaddr_in6, sin6_port)) 3436 == offsetof (struct sockaddr_in6, sin6_port))
3437 && sizeof (sa1.sin_port) == sizeof (sa6.sin6_port)); 3437 && sizeof (sa1.sin_port) == sizeof (sa6.sin6_port));
3438#endif 3438#endif
3439 if (getsockname (s, (struct sockaddr *)&sa1, &len1) == 0) 3439 DECLARE_POINTER_ALIAS (psa1, struct sockaddr, &sa1);
3440 if (getsockname (s, psa1, &len1) == 0)
3440 { 3441 {
3441 Lisp_Object service = make_number (ntohs (sa1.sin_port)); 3442 Lisp_Object service = make_number (ntohs (sa1.sin_port));
3442 contact = Fplist_put (contact, QCservice, service); 3443 contact = Fplist_put (contact, QCservice, service);
3443 /* Save the port number so that we can stash it in 3444 /* Save the port number so that we can stash it in
3444 the process object later. */ 3445 the process object later. */
3445 ((struct sockaddr_in *) sa)->sin_port = sa1.sin_port; 3446 DECLARE_POINTER_ALIAS (psa, struct sockaddr_in, sa);
3447 psa->sin_port = sa1.sin_port;
3446 } 3448 }
3447 } 3449 }
3448#endif 3450#endif
@@ -3550,9 +3552,10 @@ connect_network_socket (Lisp_Object proc, Lisp_Object addrinfos,
3550 { 3552 {
3551 struct sockaddr_storage sa1; 3553 struct sockaddr_storage sa1;
3552 socklen_t len1 = sizeof (sa1); 3554 socklen_t len1 = sizeof (sa1);
3553 if (getsockname (s, (struct sockaddr *)&sa1, &len1) == 0) 3555 DECLARE_POINTER_ALIAS (psa1, struct sockaddr, &sa1);
3556 if (getsockname (s, psa1, &len1) == 0)
3554 contact = Fplist_put (contact, QClocal, 3557 contact = Fplist_put (contact, QClocal,
3555 conv_sockaddr_to_lisp ((struct sockaddr *)&sa1, len1)); 3558 conv_sockaddr_to_lisp (psa1, len1));
3556 } 3559 }
3557#endif 3560#endif
3558 } 3561 }
@@ -4401,7 +4404,7 @@ network_interface_info (Lisp_Object ifname)
4401 4404
4402 for (it = ifap; it != NULL; it = it->ifa_next) 4405 for (it = ifap; it != NULL; it = it->ifa_next)
4403 { 4406 {
4404 struct sockaddr_dl *sdl = (struct sockaddr_dl *) it->ifa_addr; 4407 DECLARE_POINTER_ALIAS (sdl, struct sockaddr_dl, it->ifa_addr);
4405 unsigned char linkaddr[6]; 4408 unsigned char linkaddr[6];
4406 int n; 4409 int n;
4407 4410
@@ -4722,7 +4725,7 @@ server_accept_connection (Lisp_Object server, int channel)
4722 { 4725 {
4723 args[nargs++] = procname_format_in6; 4726 args[nargs++] = procname_format_in6;
4724 nargs++; 4727 nargs++;
4725 uint16_t *ip6 = (uint16_t *)&saddr.in6.sin6_addr; 4728 DECLARE_POINTER_ALIAS (ip6, uint16_t, &saddr.in6.sin6_addr);
4726 service = make_number (ntohs (saddr.in.sin_port)); 4729 service = make_number (ntohs (saddr.in.sin_port));
4727 for (int i = 0; i < 8; i++) 4730 for (int i = 0; i < 8; i++)
4728 args[nargs++] = make_number (ip6[i]); 4731 args[nargs++] = make_number (ip6[i]);