emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH] Fix use of sockaddr_in


From: Philipp Stephani
Subject: [PATCH] Fix use of sockaddr_in
Date: Sat, 13 May 2017 17:08:37 +0200

Fixes an access violation detected by AddressSanitizer.

* process.c (connect_network_socket): Use sockaddr_storage
structure instead of sockaddr_in.  Only sockaddr_storage is
guaranteed to be large enough for all address families.
---
 src/process.c | 42 ++++++++++++++++++++++++++++++++----------
 1 file changed, 32 insertions(+), 10 deletions(-)

diff --git a/src/process.c b/src/process.c
index 0edd092ef6..873db48b55 100644
--- a/src/process.c
+++ b/src/process.c
@@ -3420,16 +3420,35 @@ connect_network_socket (Lisp_Object proc, Lisp_Object 
addrinfos,
 #ifdef HAVE_GETSOCKNAME
          if (p->port == 0)
            {
-             struct sockaddr_in sa1;
+             struct sockaddr_storage sa1;
              socklen_t len1 = sizeof (sa1);
              if (getsockname (s, (struct sockaddr *)&sa1, &len1) == 0)
                {
-                 Lisp_Object service;
-                 service = make_number (ntohs (sa1.sin_port));
-                 contact = Fplist_put (contact, QCservice, service);
-                 /* Save the port number so that we can stash it in
-                    the process object later.  */
-                 ((struct sockaddr_in *)sa)->sin_port = sa1.sin_port;
+                  eassert (sizeof sa1 >= len1);
+                  in_port_t port;
+                  bool has_port;
+                  switch (sa1.ss_family)
+                    {
+                    case AF_INET:
+                      port = ((struct sockaddr_in6 *) (struct sockaddr *) 
&sa1)->sin6_port;
+                      has_port = true;
+                      break;
+                    case AF_INET6:
+                      port = ((struct sockaddr_in *) (struct sockaddr *) 
&sa1)->sin_port;
+                      has_port = true;
+                      break;
+                    default:
+                      has_port = false;
+                      break;
+                    }
+                  if (has_port)
+                    {
+                      const Lisp_Object service = make_number (ntohs (port));
+                      contact = Fplist_put (contact, QCservice, service);
+                      /* Save the port number so that we can stash it
+                         in the process object later.  */
+                      ((struct sockaddr_in *)sa)->sin_port = port;
+                    }
                }
            }
 #endif
@@ -3535,11 +3554,14 @@ connect_network_socket (Lisp_Object proc, Lisp_Object 
addrinfos,
 #ifdef HAVE_GETSOCKNAME
       if (!p->is_server)
        {
-         struct sockaddr_in sa1;
+         struct sockaddr_storage sa1;
          socklen_t len1 = sizeof (sa1);
          if (getsockname (s, (struct sockaddr *)&sa1, &len1) == 0)
-           contact = Fplist_put (contact, QClocal,
-                                 conv_sockaddr_to_lisp ((struct sockaddr 
*)&sa1, len1));
+            {
+              eassert (sizeof sa1 >= len1);
+              contact = Fplist_put (contact, QClocal,
+                                    conv_sockaddr_to_lisp ((struct sockaddr 
*)&sa1, len1));
+            }
        }
 #endif
     }
-- 
2.13.0




reply via email to

[Prev in Thread] Current Thread [Next in Thread]