summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPhilipp Stephani <phst@google.com>2020-12-30 22:33:22 +0100
committerPhilipp Stephani <phst@google.com>2020-12-30 23:04:34 +0100
commit0ea7bb3578998ebdf7c4903e7f38a8abf2e41b68 (patch)
tree1378d50b1c9a6eb5d2b863710fa8c0d01ab3281e /src
parent3a6137a498fe065cadbbf9a1f0575623155a9e55 (diff)
downloademacs-0ea7bb3578998ebdf7c4903e7f38a8abf2e41b68.tar.gz
Consistently check for FD_SETSIZE overflow.
Previously this was only checked in a few places. Now assert that file descriptors are within the expected range whenever we'd otherwise introduce undefined behavior. * src/process.c (add_read_fd, add_process_read_fd, delete_read_fd) (recompute_max_desc, delete_write_fd, compute_input_wait_mask) (compute_non_process_wait_mask, compute_non_keyboard_wait_mask) (compute_write_mask, clear_waiting_thread_info) (update_processes_for_thread_death, Fset_process_thread) (create_process, create_pty, Fmake_pipe_process) (Fprocess_datagram_address, Fset_process_datagram_address) (Fmake_serial_process, finish_after_tls_connection) (connect_network_socket, deactivate_process) (server_accept_connection, wait_reading_process_output) (read_process_output, read_and_dispose_of_process_output) (send_process, Fcontinue_process, Fprocess_send_eof) (Fprocess_filter_multibyte_p, keyboard_bit_set) (add_timer_wait_descriptor, setup_process_coding_systems): Add assertions to document and check that file descriptors are within the expected range when used as file descriptor set elements or array subscripts.
Diffstat (limited to 'src')
-rw-r--r--src/process.c42
1 files changed, 42 insertions, 0 deletions
diff --git a/src/process.c b/src/process.c
index 28ab15c9038..7c56366d8e1 100644
--- a/src/process.c
+++ b/src/process.c
@@ -465,6 +465,7 @@ add_read_fd (int fd, fd_callback func, void *data)
{
add_keyboard_wait_descriptor (fd);
+ eassert (0 <= fd && fd < FD_SETSIZE);
fd_callback_info[fd].func = func;
fd_callback_info[fd].data = data;
}
@@ -485,6 +486,7 @@ static void
add_process_read_fd (int fd)
{
add_non_keyboard_read_fd (fd);
+ eassert (0 <= fd && fd < FD_SETSIZE);
fd_callback_info[fd].flags |= PROCESS_FD;
}
@@ -495,6 +497,7 @@ delete_read_fd (int fd)
{
delete_keyboard_wait_descriptor (fd);
+ eassert (0 <= fd && fd < FD_SETSIZE);
if (fd_callback_info[fd].flags == 0)
{
fd_callback_info[fd].func = 0;
@@ -534,6 +537,7 @@ recompute_max_desc (void)
{
int fd;
+ eassert (max_desc < FD_SETSIZE);
for (fd = max_desc; fd >= 0; --fd)
{
if (fd_callback_info[fd].flags != 0)
@@ -542,6 +546,7 @@ recompute_max_desc (void)
break;
}
}
+ eassert (max_desc < FD_SETSIZE);
}
/* Stop monitoring file descriptor FD for when write is possible. */
@@ -549,6 +554,7 @@ recompute_max_desc (void)
void
delete_write_fd (int fd)
{
+ eassert (0 <= fd && fd < FD_SETSIZE);
if ((fd_callback_info[fd].flags & NON_BLOCKING_CONNECT_FD) != 0)
{
if (--num_pending_connects < 0)
@@ -571,6 +577,7 @@ compute_input_wait_mask (fd_set *mask)
int fd;
FD_ZERO (mask);
+ eassert (max_desc < FD_SETSIZE);
for (fd = 0; fd <= max_desc; ++fd)
{
if (fd_callback_info[fd].thread != NULL
@@ -593,6 +600,7 @@ compute_non_process_wait_mask (fd_set *mask)
int fd;
FD_ZERO (mask);
+ eassert (max_desc < FD_SETSIZE);
for (fd = 0; fd <= max_desc; ++fd)
{
if (fd_callback_info[fd].thread != NULL
@@ -616,6 +624,7 @@ compute_non_keyboard_wait_mask (fd_set *mask)
int fd;
FD_ZERO (mask);
+ eassert (max_desc < FD_SETSIZE);
for (fd = 0; fd <= max_desc; ++fd)
{
if (fd_callback_info[fd].thread != NULL
@@ -639,6 +648,7 @@ compute_write_mask (fd_set *mask)
int fd;
FD_ZERO (mask);
+ eassert (max_desc < FD_SETSIZE);
for (fd = 0; fd <= max_desc; ++fd)
{
if (fd_callback_info[fd].thread != NULL
@@ -660,6 +670,7 @@ clear_waiting_thread_info (void)
{
int fd;
+ eassert (max_desc < FD_SETSIZE);
for (fd = 0; fd <= max_desc; ++fd)
{
if (fd_callback_info[fd].waiting_thread == current_thread)
@@ -936,8 +947,10 @@ update_processes_for_thread_death (Lisp_Object dying_thread)
struct Lisp_Process *proc = XPROCESS (process);
pset_thread (proc, Qnil);
+ eassert (proc->infd < FD_SETSIZE);
if (proc->infd >= 0)
fd_callback_info[proc->infd].thread = NULL;
+ eassert (proc->outfd < FD_SETSIZE);
if (proc->outfd >= 0)
fd_callback_info[proc->outfd].thread = NULL;
}
@@ -1378,8 +1391,10 @@ If THREAD is nil, the process is unlocked. */)
proc = XPROCESS (process);
pset_thread (proc, thread);
+ eassert (proc->infd < FD_SETSIZE);
if (proc->infd >= 0)
fd_callback_info[proc->infd].thread = tstate;
+ eassert (proc->outfd < FD_SETSIZE);
if (proc->outfd >= 0)
fd_callback_info[proc->outfd].thread = tstate;
@@ -2108,6 +2123,7 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
fcntl (outchannel, F_SETFL, O_NONBLOCK);
/* Record this as an active process, with its channels. */
+ eassert (0 <= inchannel && inchannel < FD_SETSIZE);
chan_process[inchannel] = process;
p->infd = inchannel;
p->outfd = outchannel;
@@ -2215,6 +2231,7 @@ create_pty (Lisp_Object process)
/* Record this as an active process, with its channels.
As a result, child_setup will close Emacs's side of the pipes. */
+ eassert (0 <= pty_fd && pty_fd < FD_SETSIZE);
chan_process[pty_fd] = process;
p->infd = pty_fd;
p->outfd = pty_fd;
@@ -2308,6 +2325,7 @@ usage: (make-pipe-process &rest ARGS) */)
#endif
/* Record this as an active process, with its channels. */
+ eassert (0 <= inchannel && inchannel < FD_SETSIZE);
chan_process[inchannel] = proc;
p->infd = inchannel;
p->outfd = outchannel;
@@ -2637,6 +2655,7 @@ set up yet, this function will block until socket setup has completed. */)
return Qnil;
channel = XPROCESS (process)->infd;
+ eassert (0 <= channel && channel < FD_SETSIZE);
return conv_sockaddr_to_lisp (datagram_address[channel].sa,
datagram_address[channel].len);
}
@@ -2665,6 +2684,7 @@ set up yet, this function will block until socket setup has completed. */)
channel = XPROCESS (process)->infd;
len = get_lisp_to_sockaddr_size (address, &family);
+ eassert (0 <= channel && channel < FD_SETSIZE);
if (len == 0 || datagram_address[channel].len != len)
return Qnil;
conv_lisp_to_sockaddr (family, address, datagram_address[channel].sa, len);
@@ -3043,6 +3063,7 @@ usage: (make-serial-process &rest ARGS) */)
p->outfd = fd;
if (fd > max_desc)
max_desc = fd;
+ eassert (0 <= fd && fd < FD_SETSIZE);
chan_process[fd] = proc;
buffer = Fplist_get (contact, QCbuffer);
@@ -3213,6 +3234,7 @@ finish_after_tls_connection (Lisp_Object proc)
Fplist_get (contact, QChost),
Fplist_get (contact, QCservice));
+ eassert (p->outfd < FD_SETSIZE);
if (NILP (result))
{
pset_status (p, list2 (Qfailed,
@@ -3463,6 +3485,7 @@ connect_network_socket (Lisp_Object proc, Lisp_Object addrinfos,
#ifdef DATAGRAM_SOCKETS
if (p->socktype == SOCK_DGRAM)
{
+ eassert (0 <= s && s < FD_SETSIZE);
if (datagram_address[s].sa)
emacs_abort ();
@@ -3527,6 +3550,7 @@ connect_network_socket (Lisp_Object proc, Lisp_Object addrinfos,
inch = s;
outch = s;
+ eassert (0 <= inch && inch < FD_SETSIZE);
chan_process[inch] = proc;
fcntl (inch, F_SETFL, O_NONBLOCK);
@@ -3553,6 +3577,7 @@ connect_network_socket (Lisp_Object proc, Lisp_Object addrinfos,
if (! (connecting_status (p->status)
&& EQ (XCDR (p->status), addrinfos)))
pset_status (p, Fcons (Qconnect, addrinfos));
+ eassert (0 <= inch && inch < FD_SETSIZE);
if ((fd_callback_info[inch].flags & NON_BLOCKING_CONNECT_FD) == 0)
add_non_blocking_write_fd (inch);
}
@@ -4620,6 +4645,7 @@ deactivate_process (Lisp_Object proc)
close_process_fd (&p->open_fd[i]);
inchannel = p->infd;
+ eassert (inchannel < FD_SETSIZE);
if (inchannel >= 0)
{
p->infd = -1;
@@ -4853,6 +4879,7 @@ server_accept_connection (Lisp_Object server, int channel)
Lisp_Object name = Fformat (nargs, args);
Lisp_Object proc = make_process (name);
+ eassert (0 <= s && s < FD_SETSIZE);
chan_process[s] = proc;
fcntl (s, F_SETFL, O_NONBLOCK);
@@ -5132,6 +5159,8 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
if (! NILP (wait_for_cell) && ! NILP (XCAR (wait_for_cell)))
break;
+ eassert (max_desc < FD_SETSIZE);
+
#if defined HAVE_GETADDRINFO_A || defined HAVE_GNUTLS
{
Lisp_Object process_list_head, aproc;
@@ -5875,6 +5904,7 @@ read_process_output (Lisp_Object proc, int channel)
{
ssize_t nbytes;
struct Lisp_Process *p = XPROCESS (proc);
+ eassert (0 <= channel && channel < FD_SETSIZE);
struct coding_system *coding = proc_decode_coding_system[channel];
int carryover = p->decoding_carryover;
ptrdiff_t readmax = clip_to_bounds (1, read_process_output_max, PTRDIFF_MAX);
@@ -6039,6 +6069,7 @@ read_and_dispose_of_process_output (struct Lisp_Process *p, char *chars,
proc_encode_coding_system[p->outfd] surely points to a
valid memory because p->outfd will be changed once EOF is
sent to the process. */
+ eassert (p->outfd < FD_SETSIZE);
if (NILP (p->encode_coding_system) && p->outfd >= 0
&& proc_encode_coding_system[p->outfd])
{
@@ -6278,6 +6309,7 @@ send_process (Lisp_Object proc, const char *buf, ptrdiff_t len,
if (p->outfd < 0)
error ("Output file descriptor of %s is closed", SDATA (p->name));
+ eassert (p->outfd < FD_SETSIZE);
coding = proc_encode_coding_system[p->outfd];
Vlast_coding_system_used = CODING_ID_NAME (coding->id);
@@ -6387,6 +6419,7 @@ send_process (Lisp_Object proc, const char *buf, ptrdiff_t len,
/* Send this batch, using one or more write calls. */
ptrdiff_t written = 0;
int outfd = p->outfd;
+ eassert (0 <= outfd && outfd < FD_SETSIZE);
#ifdef DATAGRAM_SOCKETS
if (DATAGRAM_CHAN_P (outfd))
{
@@ -6837,6 +6870,7 @@ traffic. */)
struct Lisp_Process *p;
p = XPROCESS (process);
+ eassert (p->infd < FD_SETSIZE);
if (EQ (p->command, Qt)
&& p->infd >= 0
&& (!EQ (p->filter, Qt) || EQ (p->status, Qlisten)))
@@ -6964,6 +6998,7 @@ process has been transmitted to the serial port. */)
outfd = XPROCESS (proc)->outfd;
+ eassert (outfd < FD_SETSIZE);
if (outfd >= 0)
coding = proc_encode_coding_system[outfd];
@@ -7011,11 +7046,13 @@ process has been transmitted to the serial port. */)
p->open_fd[WRITE_TO_SUBPROCESS] = new_outfd;
p->outfd = new_outfd;
+ eassert (0 <= new_outfd && new_outfd < FD_SETSIZE);
if (!proc_encode_coding_system[new_outfd])
proc_encode_coding_system[new_outfd]
= xmalloc (sizeof (struct coding_system));
if (old_outfd >= 0)
{
+ eassert (old_outfd < FD_SETSIZE);
*proc_encode_coding_system[new_outfd]
= *proc_encode_coding_system[old_outfd];
memset (proc_encode_coding_system[old_outfd], 0,
@@ -7464,6 +7501,7 @@ DEFUN ("process-filter-multibyte-p", Fprocess_filter_multibyte_p,
struct Lisp_Process *p = XPROCESS (process);
if (p->infd < 0)
return Qnil;
+ eassert (p->infd < FD_SETSIZE);
struct coding_system *coding = proc_decode_coding_system[p->infd];
return (CODING_FOR_UNIBYTE (coding) ? Qnil : Qt);
}
@@ -7497,6 +7535,7 @@ keyboard_bit_set (fd_set *mask)
{
int fd;
+ eassert (max_desc < FD_SETSIZE);
for (fd = 0; fd <= max_desc; fd++)
if (FD_ISSET (fd, mask)
&& ((fd_callback_info[fd].flags & (FOR_READ | KEYBOARD_FD))
@@ -7744,6 +7783,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
void
add_timer_wait_descriptor (int fd)
{
+ eassert (0 <= fd && fd < FD_SETSIZE);
add_read_fd (fd, timerfd_callback, NULL);
fd_callback_info[fd].flags &= ~KEYBOARD_FD;
}
@@ -7806,6 +7846,7 @@ setup_process_coding_systems (Lisp_Object process)
if (inch < 0 || outch < 0)
return;
+ eassert (0 <= inch && inch < FD_SETSIZE);
if (!proc_decode_coding_system[inch])
proc_decode_coding_system[inch] = xmalloc (sizeof (struct coding_system));
coding_system = p->decode_coding_system;
@@ -7817,6 +7858,7 @@ setup_process_coding_systems (Lisp_Object process)
}
setup_coding_system (coding_system, proc_decode_coding_system[inch]);
+ eassert (0 <= outch && outch < FD_SETSIZE);
if (!proc_encode_coding_system[outch])
proc_encode_coding_system[outch] = xmalloc (sizeof (struct coding_system));
setup_coding_system (p->encode_coding_system,