aboutsummaryrefslogtreecommitdiffstats
path: root/src/process.c
diff options
context:
space:
mode:
authorPaul Eggert2016-02-25 11:57:10 -0800
committerPaul Eggert2016-02-25 11:59:13 -0800
commitc1415cc98c4bba699f870277b5311ed320df22cc (patch)
tree6c2f96166404906a96ef93390e8e314781c5a8a3 /src/process.c
parente65d4d3a5d7748aa742112a6065e1eeeac0275a6 (diff)
downloademacs-c1415cc98c4bba699f870277b5311ed320df22cc.tar.gz
emacs-c1415cc98c4bba699f870277b5311ed320df22cc.zip
Integer overflow cleanups for ports and socklen
* src/process.c (struct sockaddr_and_len, conv_sockaddr_to_lisp) (get_lisp_to_sockaddr_size, Fset_process_datagram_address) (connect_network_socket): Use ptrdiff_t, not int, for signed object sizes. This addresses only a theoretical problem, as in practice these object sizes are less than 2**31, but we might as well use the same style here as elsewhere in Emacs. (string_integer_p): Remove; all uses removed. (Fmake_network_process): Check that port number is in range. When converting an integer-string service, rely on strtol rather than rechecking the string by hand. * src/process.h, src/w32.c (conv_sockaddr_to_lisp): Adjust prototypes to match.
Diffstat (limited to 'src/process.c')
-rw-r--r--src/process.c73
1 files changed, 39 insertions, 34 deletions
diff --git a/src/process.c b/src/process.c
index 62a26c381b9..a3212445cde 100644
--- a/src/process.c
+++ b/src/process.c
@@ -302,7 +302,7 @@ static struct coding_system *proc_encode_coding_system[FD_SETSIZE];
302/* Table of `partner address' for datagram sockets. */ 302/* Table of `partner address' for datagram sockets. */
303static struct sockaddr_and_len { 303static struct sockaddr_and_len {
304 struct sockaddr *sa; 304 struct sockaddr *sa;
305 int len; 305 ptrdiff_t len;
306} datagram_address[FD_SETSIZE]; 306} datagram_address[FD_SETSIZE];
307#define DATAGRAM_CHAN_P(chan) (datagram_address[chan].sa != 0) 307#define DATAGRAM_CHAN_P(chan) (datagram_address[chan].sa != 0)
308#define DATAGRAM_CONN_P(proc) \ 308#define DATAGRAM_CONN_P(proc) \
@@ -2245,12 +2245,12 @@ usage: (make-pipe-process &rest ARGS) */)
2245 The address family of sa is not included in the result. */ 2245 The address family of sa is not included in the result. */
2246 2246
2247Lisp_Object 2247Lisp_Object
2248conv_sockaddr_to_lisp (struct sockaddr *sa, int len) 2248conv_sockaddr_to_lisp (struct sockaddr *sa, ptrdiff_t len)
2249{ 2249{
2250 Lisp_Object address; 2250 Lisp_Object address;
2251 int i; 2251 ptrdiff_t i;
2252 unsigned char *cp; 2252 unsigned char *cp;
2253 register struct Lisp_Vector *p; 2253 struct Lisp_Vector *p;
2254 2254
2255 /* Workaround for a bug in getsockname on BSD: Names bound to 2255 /* Workaround for a bug in getsockname on BSD: Names bound to
2256 sockets in the UNIX domain are inaccessible; getsockname returns 2256 sockets in the UNIX domain are inaccessible; getsockname returns
@@ -2325,10 +2325,10 @@ conv_sockaddr_to_lisp (struct sockaddr *sa, int len)
2325 2325
2326/* Get family and required size for sockaddr structure to hold ADDRESS. */ 2326/* Get family and required size for sockaddr structure to hold ADDRESS. */
2327 2327
2328static int 2328static ptrdiff_t
2329get_lisp_to_sockaddr_size (Lisp_Object address, int *familyp) 2329get_lisp_to_sockaddr_size (Lisp_Object address, int *familyp)
2330{ 2330{
2331 register struct Lisp_Vector *p; 2331 struct Lisp_Vector *p;
2332 2332
2333 if (VECTORP (address)) 2333 if (VECTORP (address))
2334 { 2334 {
@@ -2474,7 +2474,8 @@ set up yet, this function will block until socket setup has completed. */)
2474 (Lisp_Object process, Lisp_Object address) 2474 (Lisp_Object process, Lisp_Object address)
2475{ 2475{
2476 int channel; 2476 int channel;
2477 int family, len; 2477 int family;
2478 ptrdiff_t len;
2478 2479
2479 CHECK_PROCESS (process); 2480 CHECK_PROCESS (process);
2480 2481
@@ -3085,7 +3086,7 @@ connect_network_socket (Lisp_Object proc, Lisp_Object ip_addresses)
3085 int family; 3086 int family;
3086 struct sockaddr *sa = NULL; 3087 struct sockaddr *sa = NULL;
3087 int ret; 3088 int ret;
3088 int addrlen; 3089 ptrdiff_t addrlen;
3089 struct Lisp_Process *p = XPROCESS (proc); 3090 struct Lisp_Process *p = XPROCESS (proc);
3090 Lisp_Object contact = p->childp; 3091 Lisp_Object contact = p->childp;
3091 int optbits = 0; 3092 int optbits = 0;
@@ -3283,8 +3284,8 @@ connect_network_socket (Lisp_Object proc, Lisp_Object ip_addresses)
3283 memset (datagram_address[s].sa, 0, addrlen); 3284 memset (datagram_address[s].sa, 0, addrlen);
3284 if (remote = Fplist_get (contact, QCremote), !NILP (remote)) 3285 if (remote = Fplist_get (contact, QCremote), !NILP (remote))
3285 { 3286 {
3286 int rfamily, rlen; 3287 int rfamily;
3287 rlen = get_lisp_to_sockaddr_size (remote, &rfamily); 3288 ptrdiff_t rlen = get_lisp_to_sockaddr_size (remote, &rfamily);
3288 if (rlen != 0 && rfamily == family 3289 if (rlen != 0 && rfamily == family
3289 && rlen == addrlen) 3290 && rlen == addrlen)
3290 conv_lisp_to_sockaddr (rfamily, remote, 3291 conv_lisp_to_sockaddr (rfamily, remote,
@@ -3428,17 +3429,6 @@ conv_numerical_to_lisp (unsigned char *number, int length, int port)
3428} 3429}
3429#endif 3430#endif
3430 3431
3431/* Return true if STRING consists only of numerical characters. */
3432static bool
3433string_integer_p (Lisp_Object string)
3434{
3435 char *s = SSDATA (string), c;
3436 while ((c = *s++))
3437 if (c < '0' || c > '9')
3438 return false;
3439 return true;
3440}
3441
3442/* Create a network stream/datagram client/server process. Treated 3432/* Create a network stream/datagram client/server process. Treated
3443 exactly like a normal process when reading and writing. Primary 3433 exactly like a normal process when reading and writing. Primary
3444 differences are in status display and process deletion. A network 3434 differences are in status display and process deletion. A network
@@ -3617,7 +3607,7 @@ usage: (make-network-process &rest ARGS) */)
3617#ifdef HAVE_LOCAL_SOCKETS 3607#ifdef HAVE_LOCAL_SOCKETS
3618 struct sockaddr_un address_un; 3608 struct sockaddr_un address_un;
3619#endif 3609#endif
3620 int port = 0; 3610 EMACS_INT port = 0;
3621 Lisp_Object tem; 3611 Lisp_Object tem;
3622 Lisp_Object name, buffer, host, service, address; 3612 Lisp_Object name, buffer, host, service, address;
3623 Lisp_Object filter, sentinel; 3613 Lisp_Object filter, sentinel;
@@ -3807,7 +3797,7 @@ usage: (make-network-process &rest ARGS) */)
3807 error ("%s/%s getaddrinfo_a error %d", SSDATA (host), portstring, ret); 3797 error ("%s/%s getaddrinfo_a error %d", SSDATA (host), portstring, ret);
3808 3798
3809 goto open_socket; 3799 goto open_socket;
3810 } 3800 }
3811#endif /* HAVE_GETADDRINFO_A */ 3801#endif /* HAVE_GETADDRINFO_A */
3812 3802
3813#ifdef HAVE_GETADDRINFO 3803#ifdef HAVE_GETADDRINFO
@@ -3862,20 +3852,35 @@ usage: (make-network-process &rest ARGS) */)
3862 if (EQ (service, Qt)) 3852 if (EQ (service, Qt))
3863 port = 0; 3853 port = 0;
3864 else if (INTEGERP (service)) 3854 else if (INTEGERP (service))
3865 port = (unsigned short) XINT (service); 3855 port = XINT (service);
3866 /* Allow the service to be a string containing the port number,
3867 because that's allowed if you have getaddrbyname. */
3868 else if (string_integer_p (service))
3869 port = strtol (SSDATA (service), NULL, 10);
3870 else 3856 else
3871 { 3857 {
3872 struct servent *svc_info;
3873 CHECK_STRING (service); 3858 CHECK_STRING (service);
3874 svc_info = getservbyname (SSDATA (service), 3859
3875 (socktype == SOCK_DGRAM ? "udp" : "tcp")); 3860 port = -1;
3876 if (svc_info == 0) 3861 if (SBYTES (service) != 0)
3877 error ("Unknown service: %s", SDATA (service)); 3862 {
3878 port = ntohs (svc_info->s_port); 3863 /* Allow the service to be a string containing the port number,
3864 because that's allowed if you have getaddrbyname. */
3865 char *service_end;
3866 long int lport = strtol (SSDATA (service), &service_end, 10);
3867 if (service_end == SSDATA (service) + SBYTES (service))
3868 port = lport;
3869 else
3870 {
3871 struct servent *svc_info
3872 = getservbyname (SSDATA (service),
3873 socktype == SOCK_DGRAM ? "udp" : "tcp");
3874 if (svc_info)
3875 port = ntohs (svc_info->s_port);
3876 }
3877 }
3878 }
3879
3880 if (! (0 <= port && port < 1 << 16))
3881 {
3882 AUTO_STRING (unknown_service, "Unknown service: %s");
3883 xsignal1 (Qerror, CALLN (Fformat, unknown_service, service));
3879 } 3884 }
3880 3885
3881#ifndef HAVE_GETADDRINFO 3886#ifndef HAVE_GETADDRINFO