emacs-diffs
[Top][All Lists]
Advanced

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

master 0ea7bb3 4/4: Consistently check for FD_SETSIZE overflow.


From: Philipp Stephani
Subject: master 0ea7bb3 4/4: Consistently check for FD_SETSIZE overflow.
Date: Wed, 30 Dec 2020 17:08:56 -0500 (EST)

branch: master
commit 0ea7bb3578998ebdf7c4903e7f38a8abf2e41b68
Author: Philipp Stephani <phst@google.com>
Commit: Philipp Stephani <phst@google.com>

    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.
---
 src/process.c | 42 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 42 insertions(+)

diff --git a/src/process.c b/src/process.c
index 28ab15c..7c56366 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,



reply via email to

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