1
0
mirror of https://git.savannah.gnu.org/git/emacs.git synced 2024-12-26 10:49:33 +00:00

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.
This commit is contained in:
Paul Eggert 2016-02-25 11:57:10 -08:00
parent e65d4d3a5d
commit c1415cc98c
3 changed files with 41 additions and 36 deletions

View File

@ -302,7 +302,7 @@ static struct coding_system *proc_encode_coding_system[FD_SETSIZE];
/* Table of `partner address' for datagram sockets. */
static struct sockaddr_and_len {
struct sockaddr *sa;
int len;
ptrdiff_t len;
} datagram_address[FD_SETSIZE];
#define DATAGRAM_CHAN_P(chan) (datagram_address[chan].sa != 0)
#define DATAGRAM_CONN_P(proc) \
@ -2245,12 +2245,12 @@ usage: (make-pipe-process &rest ARGS) */)
The address family of sa is not included in the result. */
Lisp_Object
conv_sockaddr_to_lisp (struct sockaddr *sa, int len)
conv_sockaddr_to_lisp (struct sockaddr *sa, ptrdiff_t len)
{
Lisp_Object address;
int i;
ptrdiff_t i;
unsigned char *cp;
register struct Lisp_Vector *p;
struct Lisp_Vector *p;
/* Workaround for a bug in getsockname on BSD: Names bound to
sockets in the UNIX domain are inaccessible; getsockname returns
@ -2325,10 +2325,10 @@ conv_sockaddr_to_lisp (struct sockaddr *sa, int len)
/* Get family and required size for sockaddr structure to hold ADDRESS. */
static int
static ptrdiff_t
get_lisp_to_sockaddr_size (Lisp_Object address, int *familyp)
{
register struct Lisp_Vector *p;
struct Lisp_Vector *p;
if (VECTORP (address))
{
@ -2474,7 +2474,8 @@ set up yet, this function will block until socket setup has completed. */)
(Lisp_Object process, Lisp_Object address)
{
int channel;
int family, len;
int family;
ptrdiff_t len;
CHECK_PROCESS (process);
@ -3085,7 +3086,7 @@ connect_network_socket (Lisp_Object proc, Lisp_Object ip_addresses)
int family;
struct sockaddr *sa = NULL;
int ret;
int addrlen;
ptrdiff_t addrlen;
struct Lisp_Process *p = XPROCESS (proc);
Lisp_Object contact = p->childp;
int optbits = 0;
@ -3283,8 +3284,8 @@ connect_network_socket (Lisp_Object proc, Lisp_Object ip_addresses)
memset (datagram_address[s].sa, 0, addrlen);
if (remote = Fplist_get (contact, QCremote), !NILP (remote))
{
int rfamily, rlen;
rlen = get_lisp_to_sockaddr_size (remote, &rfamily);
int rfamily;
ptrdiff_t rlen = get_lisp_to_sockaddr_size (remote, &rfamily);
if (rlen != 0 && rfamily == family
&& rlen == addrlen)
conv_lisp_to_sockaddr (rfamily, remote,
@ -3428,17 +3429,6 @@ conv_numerical_to_lisp (unsigned char *number, int length, int port)
}
#endif
/* Return true if STRING consists only of numerical characters. */
static bool
string_integer_p (Lisp_Object string)
{
char *s = SSDATA (string), c;
while ((c = *s++))
if (c < '0' || c > '9')
return false;
return true;
}
/* Create a network stream/datagram client/server process. Treated
exactly like a normal process when reading and writing. Primary
differences are in status display and process deletion. A network
@ -3617,7 +3607,7 @@ usage: (make-network-process &rest ARGS) */)
#ifdef HAVE_LOCAL_SOCKETS
struct sockaddr_un address_un;
#endif
int port = 0;
EMACS_INT port = 0;
Lisp_Object tem;
Lisp_Object name, buffer, host, service, address;
Lisp_Object filter, sentinel;
@ -3807,7 +3797,7 @@ usage: (make-network-process &rest ARGS) */)
error ("%s/%s getaddrinfo_a error %d", SSDATA (host), portstring, ret);
goto open_socket;
}
}
#endif /* HAVE_GETADDRINFO_A */
#ifdef HAVE_GETADDRINFO
@ -3862,20 +3852,35 @@ usage: (make-network-process &rest ARGS) */)
if (EQ (service, Qt))
port = 0;
else if (INTEGERP (service))
port = (unsigned short) XINT (service);
/* Allow the service to be a string containing the port number,
because that's allowed if you have getaddrbyname. */
else if (string_integer_p (service))
port = strtol (SSDATA (service), NULL, 10);
port = XINT (service);
else
{
struct servent *svc_info;
CHECK_STRING (service);
svc_info = getservbyname (SSDATA (service),
(socktype == SOCK_DGRAM ? "udp" : "tcp"));
if (svc_info == 0)
error ("Unknown service: %s", SDATA (service));
port = ntohs (svc_info->s_port);
port = -1;
if (SBYTES (service) != 0)
{
/* Allow the service to be a string containing the port number,
because that's allowed if you have getaddrbyname. */
char *service_end;
long int lport = strtol (SSDATA (service), &service_end, 10);
if (service_end == SSDATA (service) + SBYTES (service))
port = lport;
else
{
struct servent *svc_info
= getservbyname (SSDATA (service),
socktype == SOCK_DGRAM ? "udp" : "tcp");
if (svc_info)
port = ntohs (svc_info->s_port);
}
}
}
if (! (0 <= port && port < 1 << 16))
{
AUTO_STRING (unknown_service, "Unknown service: %s");
xsignal1 (Qerror, CALLN (Fformat, unknown_service, service));
}
#ifndef HAVE_GETADDRINFO

View File

@ -250,7 +250,7 @@ extern Lisp_Object system_process_attributes (Lisp_Object);
extern void record_deleted_pid (pid_t, Lisp_Object);
struct sockaddr;
extern Lisp_Object conv_sockaddr_to_lisp (struct sockaddr *, int);
extern Lisp_Object conv_sockaddr_to_lisp (struct sockaddr *, ptrdiff_t);
extern void hold_keyboard_input (void);
extern void unhold_keyboard_input (void);
extern bool kbd_on_hold_p (void);

View File

@ -8740,7 +8740,7 @@ sys_write (int fd, const void * buffer, unsigned int count)
/* Emulation of SIOCGIFCONF and getifaddrs, see process.c. */
extern Lisp_Object conv_sockaddr_to_lisp (struct sockaddr *, int);
extern Lisp_Object conv_sockaddr_to_lisp (struct sockaddr *, ptrdiff_t);
/* Return information about network interface IFNAME, or about all
interfaces (if IFNAME is nil). */