]> git.ipfire.org Git - thirdparty/bash.git/commitdiff
modify way bash avoids running traps in subshells that haven't reset the trap strings...
authorChet Ramey <chet.ramey@case.edu>
Wed, 14 Jan 2026 16:08:22 +0000 (11:08 -0500)
committerChet Ramey <chet.ramey@case.edu>
Wed, 14 Jan 2026 16:08:22 +0000 (11:08 -0500)
13 files changed:
CWRU/CWRU.chlog
bashline.c
command.h
doc/bash.1
doc/version.texi
execute_cmd.c
general.c
jobs.c
lib/readline/doc/rluser.texi
sig.c
subst.c
tests/glob2.sub
variables.c

index 1b1a35f44c7300ce892782516bf712ae78500a01..9b63bae60d0e0e02008cd36bb1069ca12174ae18 100644 (file)
@@ -12512,3 +12512,32 @@ jobs.c
        - wait_for_background_pids: treat wait_for_single_pid returning > 256
          as an error, same as returning < 0, and check errno appropriately
          Report from Aleksey Covacevice <aleksey.covacevice@gmail.com>
+
+sig.c
+       - termsig_handler: don't try to run the exit trap if we're supposed
+         to be ignoring traps (until they're reset) in a subshell
+         environment
+
+                                   1/7
+                                   ---
+execute_cmd.c
+       - execute_in_subshell: set SUBSHELL_IGNTRAP before checking for any
+         fatal signal instead of calling clear_exit_trap(); this modifies
+         the change from 12/1
+
+                                   1/9
+                                   ---
+bashline.c
+       - shell_expand_line_internal: rename shell_expand_line(), takes an
+         additional argument saying whether or not to quote the individual
+         words in the expanded line (which changes how the line is split
+         initially, since shell-expand-line treats the line as a single
+         potentially-quoted word)
+       - shell_expand_line: call shell_expand_line_internal
+       - shell-expand-and-requote-line: new bindable command, splits the
+         line into individual words like with programmable completion,
+         expands each one, including word splitting, then quotes the
+         resultant words if necessary to prevent subsequent expansion
+       - shell_expand_and_requote_line: calls shell_expand_line_internal
+         with a third argument of 1 to force quoting
+         From a proposal by Koichi Murase <myoga.murase@gmail.com> in 2/2024
index 0f624604b802c97b5b2565fba87d272dc2977596..bfe0b6ccce425b6a09cbaedcb5b627ec3ab996e8 100644 (file)
@@ -1,6 +1,6 @@
 /* bashline.c -- Bash's interface to the readline library. */
 
-/* Copyright (C) 1987-2025 Free Software Foundation, Inc.
+/* Copyright (C) 1987-2026 Free Software Foundation, Inc.
 
    This file is part of GNU Bash, the Bourne Again SHell.
 
@@ -117,7 +117,9 @@ extern int tputs (const char *string, int nlines, int (*outx)(int));
 /* Forward declarations */
 
 /* Functions bound to keys in Readline for Bash users. */
+static int shell_expand_line_internal (int, int, int);
 static int shell_expand_line (int, int);
+static int shell_expand_and_requote_line (int, int);
 static int display_shell_version (int, int);
 
 static int bash_ignore_filenames (char **);
@@ -466,6 +468,7 @@ initialize_readline (void)
   /* Add bindable names before calling rl_initialize so they may be
      referenced in the various inputrc files. */
   rl_add_defun ("shell-expand-line", shell_expand_line, -1);
+  rl_add_defun ("shell-expand-and-requote-line", shell_expand_and_requote_line, -1);
 #ifdef BANG_HISTORY
   rl_add_defun ("history-expand-line", history_expand_line, -1);
   rl_add_defun ("magic-space", tcsh_magic_space, -1);
@@ -3005,11 +3008,12 @@ history_and_alias_expand_line (int count, int ignore)
 }
 
 /* History and alias expand the line, then perform the shell word
-   expansions by calling expand_string.  This can't use set_up_new_line()
-   because we want the variable expansions as a separate undo'able
-   set of operations. */
+   expansions by calling expand_word(). If QUOTE_WORDS is non-zero,
+   we single-quote the expanded words if they contain any shell
+   metacharacters. This can't use set_up_new_line() because we want
+   the variable expansions as a separate undoable set of operations. */
 static int
-shell_expand_line (int count, int ignore)
+shell_expand_line_internal (int count, int ignore, int quote_words)
 {
   char *new_line, *t;
   WORD_LIST *expanded_string;
@@ -3048,17 +3052,25 @@ shell_expand_line (int count, int ignore)
       /* If there is variable expansion to perform, do that as a separate
         operation to be undone. */
 
-#if 1
-      w = alloc_word_desc ();
-      w->word = savestring (rl_line_buffer);
-      w->flags = rl_explicit_arg ? (W_NOPROCSUB|W_NOCOMSUB) : 0;
-      expanded_string = expand_word (w, rl_explicit_arg ? Q_HERE_DOCUMENT : 0);
-      dispose_word (w);
-#else
-      new_line = savestring (rl_line_buffer);
-      expanded_string = expand_string (new_line, 0);
-      FREE (new_line);
-#endif
+      if (quote_words)
+       {
+         WORD_LIST *wl;
+
+         wl = split_at_delims (rl_line_buffer, strlen (rl_line_buffer), (char *)NULL, -1, 0, (int *)NULL, (int *)NULL);
+         if (rl_explicit_arg)
+           for (expanded_string = wl; expanded_string; expanded_string = expanded_string->next)
+             expanded_string->word->flags |= (W_NOPROCSUB|W_NOCOMSUB);
+         expanded_string = expand_words_shellexp (wl);
+         dispose_words (wl);
+       }
+      else
+       {
+         w = alloc_word_desc ();
+         w->word = savestring (rl_line_buffer);
+         w->flags = rl_explicit_arg ? (W_NOPROCSUB|W_NOCOMSUB) : 0;
+         expanded_string = expand_word (w, rl_explicit_arg ? Q_HERE_DOCUMENT : 0);
+         dispose_word (w);
+       }
 
       if (expanded_string == 0)
        {
@@ -3066,13 +3078,48 @@ shell_expand_line (int count, int ignore)
          new_line[0] = '\0';
        }
       else
+       new_line = string_list (expanded_string);
+
+      /* We do it this way so we can make the expansion and (optional)
+        quoting separate undoable operations. */
+      maybe_make_readline_line (new_line);
+      free (new_line);      
+
+      /* If requested, we quote the expanded words if they need it. This uses
+        split_at_delims in the same way that programmable completion does. */
+      if (quote_words)
        {
+         char *nword;
+         WORD_LIST *wl;
+
+         for (wl = expanded_string; wl; wl = wl->next)
+           {
+             t = wl->word->word;
+             if (t == 0)
+               continue;       /* XXX skip empty words */
+             nword = NULL;
+             if (*t == 0)
+               nword = sh_single_quote (t);
+             else if (ansic_shouldquote (t))
+               nword = ansic_quote (t, 0, (int *)0);
+             else if (rl_explicit_arg || sh_contains_shell_metas (t))
+               nword = sh_single_quote (t);
+
+             if (nword)
+               {
+                 free (t);
+                 wl->word->word = nword;
+               }
+           }
+
          new_line = string_list (expanded_string);
-         dispose_words (expanded_string);
+
+         maybe_make_readline_line (new_line);
+         free (new_line);
        }
 
-      maybe_make_readline_line (new_line);
-      free (new_line);
+      if (expanded_string)
+       dispose_words (expanded_string);
 
       /* Place rl_point where we think it should go. */
       if (at_end)
@@ -3092,6 +3139,19 @@ shell_expand_line (int count, int ignore)
     }
 }
 
+static int
+shell_expand_line (int count, int ignore)
+{
+  return (shell_expand_line_internal (count, ignore, 0));
+}
+
+static int
+shell_expand_and_requote_line (int count, int ignore)
+{
+  return (shell_expand_line_internal (count, ignore, 1));
+}
+
+
 /* If FIGNORE is set, then don't match files with the given suffixes when
    completing filenames.  If only one of the possibilities has an acceptable
    suffix, delete the others, else just return and let the completer
index f8196b5feaa7a6d57614f971c2c2402d9414d852..dd9ef12336df58e21641cce80d12a647ec70fd55 100644 (file)
--- a/command.h
+++ b/command.h
@@ -1,7 +1,7 @@
 /* command.h -- The structures used internally to represent commands, and
    the extern declarations of the functions used to create them. */
 
-/* Copyright (C) 1993-2022 Free Software Foundation, Inc.
+/* Copyright (C) 1993-2026 Free Software Foundation, Inc.
 
    This file is part of GNU Bash, the Bourne Again SHell.
 
@@ -126,6 +126,7 @@ enum command_type { cm_for, cm_case, cm_while, cm_if, cm_simple, cm_select,
 #define SUBSHELL_COPROC        0x40    /* subshell from a coproc pipeline */
 #define SUBSHELL_RESETTRAP 0x80        /* subshell needs to reset trap strings on first call to trap */
 #define SUBSHELL_IGNTRAP 0x100  /* subshell should reset trapped signals from trap_handler */
+#define SUBSHELL_RESETJOBS 0x200 /* subshell should clear the jobs list */
 
 /* A structure which represents a word. */
 typedef struct word_desc {
index 6e5d9ac70fd203a4f7bbb2e42cc75c47f59ff293..248c464eafee0cc73fb60105ecd0c8f62d4f6dc0 100644 (file)
@@ -5,7 +5,7 @@
 .\"    Case Western Reserve University
 .\"    chet.ramey@case.edu
 .\"
-.\"    Last Change: Wed Dec 31 18:30:12 EST 2025
+.\"    Last Change: Fri Jan  9 10:17:30 EST 2026
 .\"
 .\" For bash_builtins, strip all but "SHELL BUILTIN COMMANDS" section
 .\" For rbash, strip all but "RESTRICTED SHELL" section
@@ -22,7 +22,7 @@
 .ds zX \" empty
 .if \n(zZ=1 .ig zZ
 .if \n(zY=1 .ig zY
-.TH BASH 1 "2025 December 31" "GNU Bash 5.3"
+.TH BASH 1 "2026 January 9" "GNU Bash 5.3"
 .\"
 .ie \n(.g \{\
 .ds ' \(aq
@@ -110,8 +110,8 @@ bash \- GNU Bourne-Again SHell
 [options]
 [command_string | file]
 .SH COPYRIGHT
-.if n Bash is Copyright (C) 1989-2025 by the Free Software Foundation, Inc.
-.if t Bash is Copyright \(co 1989-2025 by the Free Software Foundation, Inc.
+.if n Bash is Copyright (C) 1989-2026 by the Free Software Foundation, Inc.
+.if t Bash is Copyright \(co 1989-2026 by the Free Software Foundation, Inc.
 .SH DESCRIPTION
 .B Bash
 is a command language interpreter that
@@ -7761,7 +7761,8 @@ last word, as if the
 history expansion had been specified.
 .TP
 .B shell\-expand\-line (M\-C\-e)
-Expand the line by performing shell word expansions.
+Expand the line by performing shell word expansions,
+treating the line as a single shell word.
 This performs alias and history expansion,
 \fB$\fP\*'\fIstring\fP\*' and \fB$\fP\*"\fIstring\fP\*" quoting,
 tilde expansion, parameter and variable expansion, arithmetic expansion,
@@ -7773,6 +7774,24 @@ See
 .B "HISTORY EXPANSION"
 below for a description of history expansion.
 .TP
+.B shell\-expand\-and\-requote\-line ()
+Expand the line by performing shell word expansions,
+splitting the line into shell words in the same way as for
+programmable completion.
+This performs alias and history expansion,
+\fB$\fP\*'\fIstring\fP\*' and \fB$\fP\*"\fIstring\fP\*" quoting,
+tilde expansion, parameter and variable expansion, arithmetic expansion,
+command and process substitution,
+word splitting, and quote removal 
+on each word, then quotes the resulting words if necessary to
+prevent further expansion.
+An explicit argument suppresses command and process substitution 
+and quotes each resultant word.
+As usual, double-quoting a word will suppress word splitting.     
+This can be useful when combined with suppressing command substitution,
+for instance, so the words in the command substitution aren't
+quoted individually.
+.TP
 .B history\-expand\-line (M\-\*^)
 Perform history expansion on the current line.
 See
index 925fd9938b0397837aec2e67482cc671e86c5301..8a06272e0908547e492a2d8659010099199dc9b5 100644 (file)
@@ -1,11 +1,11 @@
 @ignore
-Copyright (C) 1988-2025 Free Software Foundation, Inc.
+Copyright (C) 1988-2026 Free Software Foundation, Inc.
 @end ignore
 
-@set LASTCHANGE Wed Dec 31 18:26:37 EST 2025
+@set LASTCHANGE Fri Jan  9 10:17:58 EST 2026
 
 @set EDITION 5.3
 @set VERSION 5.3
 
-@set UPDATED 31 December 2025
-@set UPDATED-MONTH December 2025
+@set UPDATED 9 January 2026
+@set UPDATED-MONTH January 2026
index db1806e8719df4332fbccbe233aa5aef2106cc32..bb859294eb1b466808bba1ac7b5ac5c843d7165c 100644 (file)
@@ -1,6 +1,6 @@
 /* execute_cmd.c -- Execute a COMMAND structure. */
 
-/* Copyright (C) 1987-2025 Free Software Foundation, Inc.
+/* Copyright (C) 1987-2026 Free Software Foundation, Inc.
 
    This file is part of GNU Bash, the Bourne Again SHell.
 
@@ -1680,13 +1680,13 @@ execute_in_subshell (COMMAND *command, int asynchronous, int pipe_in, int pipe_o
 
   if (user_subshell)
     {
-      subshell_environment = SUBSHELL_PAREN  /* XXX */
+      subshell_environment = SUBSHELL_PAREN|SUBSHELL_IGNTRAP;  /* XXX */
       if (asynchronous)
        subshell_environment |= SUBSHELL_ASYNC;
     }
   else
     {
-      subshell_environment = 0;                        /* XXX */
+      subshell_environment = SUBSHELL_IGNTRAP;                 /* XXX */
       if (asynchronous)
        subshell_environment |= SUBSHELL_ASYNC;
       if (pipe_in != NO_PIPE || pipe_out != NO_PIPE)
@@ -1695,10 +1695,6 @@ execute_in_subshell (COMMAND *command, int asynchronous, int pipe_in, int pipe_o
        subshell_environment |= SUBSHELL_COPROC;
     }
 
-  /* clear the exit trap before checking for fatal signals, but don't free
-     the trap command (see below). */
-  clear_exit_trap (0);
-
   QUIT;
   CHECK_TERMSIG;
 
index aeffda5c94d59bdcefac17148b52caf6a28cccc1..645e337b43ad9a708d0af817def679b14560b0cd 100644 (file)
--- a/general.c
+++ b/general.c
@@ -1,6 +1,6 @@
 /* general.c -- Stuff that is used by all files. */
 
-/* Copyright (C) 1987-2025 Free Software Foundation, Inc.
+/* Copyright (C) 1987-2026 Free Software Foundation, Inc.
 
    This file is part of GNU Bash, the Bourne Again SHell.
 
@@ -456,6 +456,24 @@ valid_function_word (WORD_DESC *word, int flags)
       err_invalidid (name);
       return (0);
     }
+
+#if 0  /*TAG: bash-5.4 kre@munnari.oz.au 6/11/2025 */
+  if (word->flags & W_QUOTED)
+    {
+      char *newname;
+
+      newname = string_quote_removal (name, 0);
+      if (newname == 0)
+       {
+         err_invalidid (name);
+         return (0);
+       }
+      free (word->word);
+      word->word = name = newname;
+      word->flags &= ~W_QUOTED;
+    }
+#endif
+  
   /* POSIX interpretation 383 -- this is an application requirement, but the
      shell should enforce it rather than allow a script to define a function
      that will never be called. */
diff --git a/jobs.c b/jobs.c
index 0b4b86223c40af09eb810364deb60386885153c4..201a6b022bc0f0b9cc419be0fbd888b74e3bec82 100644 (file)
--- a/jobs.c
+++ b/jobs.c
@@ -3,7 +3,7 @@
 /* This file works with both POSIX and BSD systems.  It implements job
    control. */
 
-/* Copyright (C) 1989-2025 Free Software Foundation, Inc.
+/* Copyright (C) 1989-2026 Free Software Foundation, Inc.
 
    This file is part of GNU Bash, the Bourne Again SHell.
 
index 45b9a8fec97af5fe001c2c334458095651e7f93c..9830c11cf26a61cb928f61b74ba73de63d3f2ac3 100644 (file)
@@ -2065,13 +2065,33 @@ If a numeric argument is supplied, append a @samp{*} before
 pathname expansion.
 
 @item shell-expand-line (M-C-e)
-Expand the line by performing shell word expansions.  
+Expand the line by performing shell word expansions,
+treating the line as a single shell word.
 This performs alias and history expansion,
 $'@var{string}' and $"@var{string}" quoting,
 tilde expansion, parameter and variable expansion, arithmetic expansion,
 command and process substitution,
-word splitting, and quote removal.  
-An explicit argument suppresses command and process substitution.
+word splitting, and quote removal.
+An explicit argument suppresses command and process substitution and
+treats the line as if it were quoted as part of a here-document.
+
+@item shell-expand-and-requote-line ()
+Expand the line by performing shell word expansions,
+splitting the line into shell words in the same way as for
+programmable completion.
+This performs alias and history expansion,
+$'@var{string}' and $"@var{string}" quoting,
+tilde expansion, parameter and variable expansion, arithmetic expansion,
+command and process substitution,
+word splitting, and quote removal
+on each word, then quotes the resulting words if necessary to
+prevent further expansion.
+An explicit argument suppresses command and process substitution
+and quotes each resultant word.
+As usual, double-quoting a word will suppress word splitting.
+This can be useful when combined with suppressing command substitution,
+for instance, so the words in the command substitution aren't
+quoted individually.
 
 @item history-expand-line (M-^)
 Perform history expansion on the current line.
diff --git a/sig.c b/sig.c
index 6af1d5f02b85234a5f03ddf751df8da428c8e640..70858d539e150e88803f6988d85b506b18211ed9 100644 (file)
--- a/sig.c
+++ b/sig.c
@@ -1,6 +1,6 @@
 /* sig.c - interface for shell signal handlers and signal initialization. */
 
-/* Copyright (C) 1994-2024 Free Software Foundation, Inc.
+/* Copyright (C) 1994-2026 Free Software Foundation, Inc.
 
    This file is part of GNU Bash, the Bourne Again SHell.
 
@@ -644,7 +644,10 @@ termsig_handler (int sig)
   interrupt_execution = retain_fifos = executing_funsub = 0;
   comsub_ignore_return = return_catch_flag = wait_intr_flag = 0;
 
-  run_exit_trap ();    /* XXX - run exit trap possibly in signal context? */
+  /* Don't run the exit trap if we're supposed to be ignoring traps in a
+     subshell environment. */
+  if ((subshell_environment & SUBSHELL_IGNTRAP) == 0)
+    run_exit_trap ();  /* XXX - run exit trap possibly in signal context? */
 
   kill_shell (sig);
 }
diff --git a/subst.c b/subst.c
index eabea2aaec7a4b15802abbd0820b2eaacf10a576..c330bf8c2767ffe46c6a41aaf01bb3fd5443ca1a 100644 (file)
--- a/subst.c
+++ b/subst.c
@@ -4,7 +4,7 @@
 /* ``Have a little faith, there's magic in the night.  You ain't a
      beauty, but, hey, you're alright.'' */
 
-/* Copyright (C) 1987-2025 Free Software Foundation, Inc.
+/* Copyright (C) 1987-2026 Free Software Foundation, Inc.
 
    This file is part of GNU Bash, the Bourne Again SHell.
 
@@ -7143,10 +7143,8 @@ function_substitute (char *string, int quoted, int flags)
        add_unwind_protect (uw_unbind_localvar, "REPLY");
     }
 
-#if 1  /* TAG:bash-5.3 myoga.murase@gmail.com 04/30/2024 */
   old_frozen = freeze_jobs_list (-1);
   add_unwind_protect (uw_lastpipe_cleanup, (void *) (intptr_t) old_frozen);
-#endif
 
 #if defined (JOB_CONTROL)
   unwind_protect_var (pipeline_pgrp);
@@ -8768,7 +8766,7 @@ string_var_assignment (SHELL_VAR *v, char *s)
     sprintf (ret, "declare -%s %s", flags, v->name);   /* just attributes, unset */
   else if (i > 0)
     sprintf (ret, "declare -%s %s=%s", flags, v->name, val);   /* attributes, set */
-#if 1 /*TAG: bash-5.3 tentative */
+#if 1 /*TAG: bash-5.4 tentative */
   else if (i == 0 && val && local_p (v) && variable_context == v->context)
     sprintf (ret, "declare %s=%s", v->name, val);      /* set local variable at current scope */
   else if (i == 0 && val == 0 && local_p (v) && variable_context == v->context)
index 8f79387f4f5bc9941e8323e4f6edd2c4a561b1a9..c6c860dedc22ddc10cb0f467e413bf344711b0fa 100644 (file)
@@ -16,7 +16,7 @@
 # this locale causes problems all over the place
 if [ -z "$ZH_LOCALE" ]; then
         echo "${CSTART}glob2.sub: warning${CEND}: you do not have the zh_TW.big5 locale installed;" >&2
-        echo "${TAB}glob2.sub: that may cause some of these tests to fail." >&2
+        echo "${TAB}that may cause some of these tests to fail." >&2
        ZH_LOCALE=$ZH_DEFAULT
 fi
 
index a43f5316291bfc86f1e12087ef3fe8df51af98d7..2cf482fdec5a1059df326e4c3ca7b2e398f6d95b 100644 (file)
@@ -1,6 +1,6 @@
 /* variables.c -- Functions for hacking shell variables. */
 
-/* Copyright (C) 1987-2025 Free Software Foundation, Inc.
+/* Copyright (C) 1987-2026 Free Software Foundation, Inc.
 
    This file is part of GNU Bash, the Bourne Again SHell.
 
@@ -455,7 +455,7 @@ initialize_shell_variables (char **env, int privmode)
          STREQN (BASHARRAY_SUFFIX, name + char_index - BASHARRAY_SUFFLEN, BASHARRAY_SUFFLEN) &&
          *string == '(' && string[1] == '[' && string[strlen (string) - 1] == ')')
        {
-         size_t namelen, slen;
+         size_t namelen;
          char *tname;          /* desired imported array variable name */
 
          namelen = char_index - BASHARRAY_PREFLEN - BASHARRAY_SUFFLEN;