]> git.ipfire.org Git - thirdparty/bash.git/commitdiff
fix for rare readline case where read(2) succeeds but also gets a signal as it is...
authorChet Ramey <chet.ramey@case.edu>
Fri, 22 Aug 2025 20:10:45 +0000 (16:10 -0400)
committerChet Ramey <chet.ramey@case.edu>
Fri, 22 Aug 2025 20:10:45 +0000 (16:10 -0400)
CWRU/CWRU.chlog
bashline.c
lib/readline/input.c
tests/test-glue-functions [deleted file]

index 7d0ececa7d6d8695e21d5c0c0b3dbdbeab0a1daf..e0484010b67883abe0a54a544096497748fd5aa8 100644 (file)
@@ -11625,3 +11625,28 @@ lib/readline/isearch.c
          anything else that would cause signals to be processed.
          Report and fix from Grisha Levit <grishalevit@gmail.com> based on
          a report from penguin p <tgckpg@gmail.com>
+
+                                  8/21
+                                  ----
+lib/readline/input.c
+       - rl_getc: it is possible, though extremely unlikely, for read(2)
+         to both succeed (result == 1) and receive a signal
+         (_rl_caught_signal != 0).
+         We know we have a signal we're interested in, since readline's
+         handler was called, so we want to handle it immediately and defer
+         returning the character we read until the next time through the loop.
+         From a report from penguin p <tgckpg@gmail.com>
+       - rl_getc: if the application's SIGINT signal handler returns without
+         longjmping or exiting the program, make sure to abort out of
+         searches and numeric arguments, because the readline signal handler
+         has freed necessary state. Previously we did this only for the
+         callback interface
+
+                                  8/22
+                                  ----
+bashline.c
+       - bash_quote_filename: only check whether the file exists and change
+         the quote character accordingly if we have a single match.
+         Otherwise, it's a prefix and likely doesn't exist, so we'll stick
+         with the default backslash completion quoting style.
+         Fixes completion quoting issue from Aaron Laws <dartme18@gmail.com>
index a980718fa273a74b33d80abdb5df7eabb3d4ccd3..1ee70358ff8aacd3d3202edc32531e1f8d3748c2 100644 (file)
@@ -4415,9 +4415,11 @@ bash_quote_filename (char *s, int rtype, char *qcp)
      quoted correctly using backslashes (a backslash-newline pair is
      special to the shell parser). */
   expchar = nextch = closer = 0;
+  /* Only check whether the file exists if we're quoting a single completion.
+     Otherwise, it's a common prefix and probably doesn't exist. */
   if (*qcp == '\0' && cs == COMPLETE_BSQUOTE && dircomplete_expand == 0 &&
       (expchar = bash_check_expchar (s, 0, &nextch, &closer)) &&
-      file_exists (s) == 0)
+      rtype == SINGLE_MATCH && file_exists (s) == 0)
     {
       /* If it looks like the name is subject to expansion, see if we want to
         double-quote it. */
index 3383edb678a99593b935ccc5d2f86b869ef45198..83cf35041f5c484d753502b48b150cec88e29234 100644 (file)
@@ -825,8 +825,14 @@ rl_read_key (void)
        {
          if (rl_get_char (&c) == 0)
            c = (*rl_getc_function) (rl_instream);
-/* fprintf(stderr, "rl_read_key: calling RL_CHECK_SIGNALS: _rl_caught_signal = %d\r\n", _rl_caught_signal); */
+if (_rl_caught_signal)
+ {
+fprintf(stderr, "rl_read_key: calling RL_CHECK_SIGNALS: c = %d _rl_caught_signal = %d\r\n", c, _rl_caught_signal);
+   if (c > 0)
+     rl_stuff_char (c);
+   c = -1;
          RL_CHECK_SIGNALS ();
+ }
        }
     }
 
@@ -837,13 +843,14 @@ int
 rl_getc (FILE *stream)
 {
   int result, ostate, osig;
-  unsigned char c;
+  unsigned char c, savec;
   int fd;
 #if defined (HAVE_PSELECT) || defined (HAVE_SELECT)
   sigset_t empty_set;
   fd_set readfds;
 #endif
 
+  savec = 0;
   fd = fileno (stream);
   while (1)
     {
@@ -859,12 +866,19 @@ rl_getc (FILE *stream)
         chance to react or abort some current operation that gets cleaned
         up by rl_callback_sigcleanup(). If not, we'll just run through the
         loop again. */
-      if (osig != 0 && (ostate & RL_STATE_CALLBACK))
+      if (osig != 0 && (ostate & RL_STATE_CALLBACK))   /* XXX - when not in callback mode also? */
        goto postproc_signal;
 #endif
 
       /* We know at this point that _rl_caught_signal == 0 */
 
+      if (savec > 0)
+       {
+         c = savec;
+         savec = 0;
+         return c;
+       }
+
 #if defined (__MINGW32__)
       if (isatty (fd))
        return (_getch ());     /* "There is no error return." */
@@ -888,6 +902,20 @@ rl_getc (FILE *stream)
       if (result >= 0)
        result = read (fd, &c, sizeof (unsigned char));
 
+/* fprintf(stderr, "rl_getc: read result = %d errno = %d _rl_caught_signal = %d\n", result, errno, _rl_caught_signal); */
+      /* It is possible, though extremely unlikely, for read to both succeed
+        (result == 1) and receive a signal (_rl_caught_signal != 0). We
+        know we have a signal we're interested in, since readline's handler
+        was called, so we want to handle it below and defer returning the
+        character we read until the next time through the loop. */
+      if (result > 0 && _rl_caught_signal != 0)
+       {
+         if (c > 0)    /* if result == 1 we assume that c is valid */
+           savec = c;  /* one level of pushback */
+         result = -1;
+         errno = EINTR;
+       }
+
       if (result == sizeof (unsigned char))
        return (c);
 
@@ -923,7 +951,7 @@ rl_getc (FILE *stream)
 #undef X_EWOULDBLOCK
 #undef X_EAGAIN
 
-/* fprintf(stderr, "rl_getc: result = %d errno = %d\n", result, errno); */
+/* fprintf(stderr, "rl_getc: read result = %d errno = %d _rl_caught_signal = %d\n", result, errno, _rl_caught_signal); */
 
       /* Handle errors here. */
       osig = _rl_caught_signal;
@@ -975,11 +1003,11 @@ postproc_signal:
         call the application's signal event hook. */
       if (rl_signal_event_hook)
        (*rl_signal_event_hook) ();
-#if defined (READLINE_CALLBACKS)
-      else if (osig == SIGINT && (ostate & RL_STATE_CALLBACK) && (ostate & (RL_STATE_ISEARCH|RL_STATE_NSEARCH|RL_STATE_NUMERICARG)))
+      /* If the application's SIGINT handler returns, make sure we abort out of
+        searches and numeric arguments because we've freed necessary state. */
+      if (osig == SIGINT && (ostate & (RL_STATE_ISEARCH|RL_STATE_NSEARCH|RL_STATE_NUMERICARG)))
         /* just these cases for now */
         _rl_abort_internal ();
-#endif
     }
 }
 
diff --git a/tests/test-glue-functions b/tests/test-glue-functions
deleted file mode 100644 (file)
index 07ad821..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-# shell functions to include in multiple test files
-
-# squeeze out blanks to avoid white space differences in od implementations
-_intl_normalize_spaces()
-{
-       sed -e 's/[[:space:]]\{1,\}/ /g' -e 's/[[:space:]]*$//'
-}
-
-# avoid whitespace differences in wc implementations
-_cut_leading_spaces()
-{
-       sed -e 's/^[    ]*//g'
-}