mirror of
git://git.sv.gnu.org/emacs.git
synced 2026-02-16 17:24:23 +00:00
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.
This commit is contained in:
parent
3a6137a498
commit
0ea7bb3578
1 changed files with 42 additions and 0 deletions
|
|
@ -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,
|
||||
|
|
|
|||
Loading…
Reference in a new issue