From: Chet Ramey Date: Wed, 20 Aug 2025 15:08:28 +0000 (-0400) Subject: fix for nofork comsubs undoing enclosing command's redirections; fix for binding... X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=086456835944d1a3098a026646144573deafc917;p=thirdparty%2Fbash.git fix for nofork comsubs undoing enclosing command's redirections; fix for binding _ variable in the temporary environment; fix for crash when making special variables arrays; accommodate IFS as array variable; fix for SIGINT arriving while cleaning up a readline incremental search --- diff --git a/CWRU/CWRU.chlog b/CWRU/CWRU.chlog index fc2b78c5..7d0ececa 100644 --- a/CWRU/CWRU.chlog +++ b/CWRU/CWRU.chlog @@ -11586,3 +11586,42 @@ builtins/declare.def an invalid value for a nameref variable, but the original value is valid, add an error message for the assignment error Report from Oğuz + + 8/12 + ---- +subst.c + - function_substitute: unwind-protect redirection_undo_list and + exec_redirection_undo_list so the funsub command doesn't undo them + prematurely + Report from jdhedden@gmail.com + + 8/13 + ---- +execute_cmd.c + - bind_lastarg: don't try to bind the argument in the temporary + environment; just skip that and bind in the closest enclosing + scope + Report from Nathan Mills + + 8/15 + ---- +arrayfunc.c + - convert_var_to_array,convert_var_to_assoc: call + stupidly_hack_special_variables to clean up any state associated + with the variable (e.g., IFS). + Report from Nathan Mills + +subst.c + - setifs: if a script attempts to make IFS an array variable, use + element 0 or "0" as appropriate. + Report from Nathan Mills + + 8/19 + ---- +lib/readline/isearch.c + - _rl_isearch_cleanup: to avoid problems caused by calling this from + normal isearch termination and from signal cleanup code, turn off + the RL_STATE_ISEARCH flag and set _rl_iscxt to NULL before doing + anything else that would cause signals to be processed. + Report and fix from Grisha Levit based on + a report from penguin p diff --git a/MANIFEST b/MANIFEST index 78143bc8..5c084e57 100644 --- a/MANIFEST +++ b/MANIFEST @@ -942,7 +942,7 @@ examples/shellmath/testCases.in f examples/shellmath/timingData.txt f tests/README f tests/COPYRIGHT f -tests/test-glue-functions f +tests/test-aux-functions f tests/alias.tests f tests/alias1.sub f tests/alias2.sub f diff --git a/arrayfunc.c b/arrayfunc.c index 715460d5..33000f71 100644 --- a/arrayfunc.c +++ b/arrayfunc.c @@ -102,6 +102,7 @@ convert_var_to_array (SHELL_VAR *var) /* Since namerefs can't be array variables, turn off nameref attribute */ VUNSETATTR (var, att_nameref); + stupidly_hack_special_variables (var->name); return var; } @@ -139,6 +140,7 @@ convert_var_to_assoc (SHELL_VAR *var) /* Since namerefs can't be array variables, turn off nameref attribute */ VUNSETATTR (var, att_nameref); + stupidly_hack_special_variables (var->name); return var; } diff --git a/execute_cmd.c b/execute_cmd.c index 94214841..a68c5a1f 100644 --- a/execute_cmd.c +++ b/execute_cmd.c @@ -4156,7 +4156,7 @@ bind_lastarg (char *arg) if (arg == 0) arg = ""; - var = bind_variable ("_", arg, 0); + var = bind_variable ("_", arg, ASS_NOTEMPENV); if (var) VUNSETATTR (var, att_exported); } diff --git a/lib/readline/isearch.c b/lib/readline/isearch.c index 7b845c20..6cb1879d 100644 --- a/lib/readline/isearch.c +++ b/lib/readline/isearch.c @@ -889,12 +889,14 @@ opcode_dispatch: int _rl_isearch_cleanup (_rl_search_cxt *cxt, int r) { + RL_UNSETSTATE(RL_STATE_ISEARCH); + if (cxt == 0) + return (r != 0); + + _rl_iscxt = 0; if (r >= 0) _rl_isearch_fini (cxt); _rl_scxt_dispose (cxt, 0); - _rl_iscxt = 0; - - RL_UNSETSTATE(RL_STATE_ISEARCH); return (r != 0); } diff --git a/lib/readline/rlprivate.h b/lib/readline/rlprivate.h index eb0495f9..c8cb6736 100644 --- a/lib/readline/rlprivate.h +++ b/lib/readline/rlprivate.h @@ -446,8 +446,10 @@ extern void _rl_signal_handler (int); extern void _rl_block_sigint (void); extern void _rl_release_sigint (void); +extern int _rl_sigint_blocked_p (void); extern void _rl_block_sigwinch (void); extern void _rl_release_sigwinch (void); +extern int _rl_sigwinch_blocked_p (void); extern void _rl_state_sigcleanup (void); diff --git a/lib/readline/signals.c b/lib/readline/signals.c index 5a070d77..73ae5670 100644 --- a/lib/readline/signals.c +++ b/lib/readline/signals.c @@ -680,6 +680,12 @@ _rl_release_sigint (void) RL_CHECK_SIGNALS (); } +int +_rl_sigint_blocked_p (void) +{ + return sigint_blocked; +} + /* Cause SIGWINCH to not be delivered until the corresponding call to release_sigwinch(). */ void @@ -736,6 +742,12 @@ _rl_release_sigwinch (void) sigwinch_blocked = 0; } +int +_rl_sigwinch_blocked_p (void) +{ + return sigwinch_blocked; +} + /* **************************************************************** */ /* */ /* Echoing special control characters */ diff --git a/parse.y b/parse.y index 462953b7..b698f86b 100644 --- a/parse.y +++ b/parse.y @@ -2500,6 +2500,8 @@ shell_getc (int remove_quoted_newline) something on the pushed list of strings, then we don't want to go off and get another line. We let the code down below handle it. */ + /* If we're reading input from the keyboard or from a file, fetch + another line from the current source. */ if (!shell_input_line || ((!shell_input_line[shell_input_line_index]) && (pushed_string_list == (STRING_SAVER *)NULL))) #else /* !ALIAS && !DPAREN_ARITHMETIC */ @@ -2741,11 +2743,11 @@ shell_getc (int remove_quoted_newline) going to be removing quoted newlines, since that will eat the backslash. Add another backslash instead (will be removed by word expansion). */ - if (bash_input.type == st_string && expanding_alias() == 0 && last_was_backslash && c == EOF && remove_quoted_newline) + if (bash_input.type == st_string && expanding_alias () == 0 && last_was_backslash && c == EOF && remove_quoted_newline) shell_input_line[shell_input_line_len] = '\\'; - else if (bash_input.type == st_bstream && expanding_alias() == 0 && last_was_backslash && c == EOF && remove_quoted_newline) + else if (bash_input.type == st_bstream && expanding_alias () == 0 && last_was_backslash && c == EOF && remove_quoted_newline) shell_input_line[shell_input_line_len] = '\\'; - else if (interactive == 0 && bash_input.type == st_stream && expanding_alias() == 0 && last_was_backslash && c == EOF && remove_quoted_newline) + else if (interactive == 0 && bash_input.type == st_stream && expanding_alias () == 0 && last_was_backslash && c == EOF && remove_quoted_newline) shell_input_line[shell_input_line_len] = '\\'; else shell_input_line[shell_input_line_len] = '\n'; @@ -2905,6 +2907,18 @@ pop_alias: shell_input_line_index = 0; goto restart_read; } + +#if 0 /*TAG:bash-5.4 wyeth2485@gmail.com 8/15/2025 */ + /* When we're reading input from a string, we don't increment line_number + until now. If we're being called from read_token_word(), this will be + pushed back into the input string with shell_ungetc for the next call + to read_token() to consume. We don't want to increment line_number + twice, so this requires cooperation from shell_ungetc (decrement + line_number if we're pushing back a newline while parsing an alias + expansion). */ + if (uc == '\n' && expanding_alias () && pushed_string_list->flags == PSH_ALIAS) + line_number++; +#endif #endif return (uc); @@ -2922,6 +2936,11 @@ shell_ungetc (int c) shell_input_line[--shell_input_line_index] = c; else eol_ungetc_lookahead = c; + +#if 0 /*TAG:bash-5.4 wyeth2485@gmail.com 8/15/2025 */ + if (c == '\n' && expanding_alias () && heredoc_string == 0 && line_number > 0) + line_number--; +#endif } /* Push S back into shell_input_line; updating shell_input_line_index */ diff --git a/subst.c b/subst.c index 3be17a85..fd7262a4 100644 --- a/subst.c +++ b/subst.c @@ -206,6 +206,8 @@ extern int wordexp_only; extern int singlequote_translations; extern int extended_quote; +extern REDIRECT *exec_redirection_undo_list, *redirection_undo_list; + #if !defined (HAVE_WCSDUP) && defined (HANDLE_MULTIBYTE) extern wchar_t *wcsdup (const wchar_t *); #endif @@ -7022,7 +7024,12 @@ function_substitute (char *string, int quoted, int flags) add_unwind_protect (uw_restore_pipestatus_array, psa); } #endif - + + unwind_protect_pointer (redirection_undo_list); + redirection_undo_list = NULL; + unwind_protect_pointer (exec_redirection_undo_list); + exec_redirection_undo_list = NULL; + subst_assign_varlist = 0; temporary_env = 0; @@ -12358,11 +12365,15 @@ word_list_quote_removal (WORD_LIST *list, int quoted) void setifs (SHELL_VAR *v) { - char *t; + char *t, *value; unsigned char uc; ifs_var = v; - ifs_value = (v && value_cell (v)) ? value_cell (v) : " \t\n"; + /* If we do not want to support IFS as an array variable here, check that + V is not an array (array_p(v) == 0 && assoc_p (v) == 0) as part of the + test to call get_variable_value and set VALUE to NULL if it is. */ + value = v ? get_variable_value (v) : (char *)NULL; + ifs_value = (v && value) ? value : " \t\n"; ifs_is_set = ifs_var != 0; ifs_is_null = ifs_is_set && (*ifs_value == 0); diff --git a/tests/glob2.sub b/tests/glob2.sub index 0e0482dc..c5263775 100644 --- a/tests/glob2.sub +++ b/tests/glob2.sub @@ -11,7 +11,7 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . # -. ./test-glue-functions +. ./test-aux-functions # this locale causes problems all over the place if locale -a | grep -i '^zh_TW\.big5' >/dev/null ; then diff --git a/tests/history7.sub b/tests/history7.sub index 9c9d27b4..cbb23381 100644 --- a/tests/history7.sub +++ b/tests/history7.sub @@ -12,7 +12,7 @@ # along with this program. If not, see . # # test history file truncation for various values of $HISTFILESIZE -. ./test-glue-functions +. ./test-aux-functions : ${THIS_SH:=./bash} : ${TMPDIR:=/var/tmp} diff --git a/tests/intl.tests b/tests/intl.tests index 990d782d..2a4b26e0 100644 --- a/tests/intl.tests +++ b/tests/intl.tests @@ -49,7 +49,7 @@ set a b printf '%s\n' "$*" -. ./test-glue-functions +. ./test-aux-functions printf '%s' "$*" | od -b | _intl_normalize_spaces diff --git a/tests/intl3.sub b/tests/intl3.sub index 56c86780..b4d571ed 100644 --- a/tests/intl3.sub +++ b/tests/intl3.sub @@ -11,7 +11,7 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . # -. ./test-glue-functions +. ./test-aux-functions # more tests to make sure that IFS splits on characters, not bytes export LANG=en_US.UTF-8 diff --git a/tests/nameref.right b/tests/nameref.right index af86df52..ad0fdac7 100644 --- a/tests/nameref.right +++ b/tests/nameref.right @@ -534,6 +534,7 @@ declare -a array=([0]="one" [1]="two" [2]="three") declare -ai a=([0]="5") declare -ai a=([0]="6") declare -ai a=([0]="42") +./nameref23.sub: line 28: declare: a[0]: expands to invalid variable name for name reference declare -ai a=([0]="1") ./nameref23.sub: line 29: declare: b: not found declare -ai a=([0]="1") diff --git a/tests/nquote3.sub b/tests/nquote3.sub index d1480c0b..cfec48b5 100644 --- a/tests/nquote3.sub +++ b/tests/nquote3.sub @@ -1,4 +1,4 @@ -. ./test-glue-functions +. ./test-aux-functions recho $'\c?' diff --git a/tests/nquote5.sub b/tests/nquote5.sub index 97cbadc4..f5b928d1 100644 --- a/tests/nquote5.sub +++ b/tests/nquote5.sub @@ -11,7 +11,7 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . # -. test-glue-functions +. test-aux-functions recho $( echo a$'\01)'b ) recho $( echo ab ) diff --git a/tests/posixpipe.tests b/tests/posixpipe.tests index 3fe5f770..c4eca6cc 100644 --- a/tests/posixpipe.tests +++ b/tests/posixpipe.tests @@ -58,6 +58,6 @@ time -p -- echo a time -- : # this should print timing information -. ./test-glue-functions +. ./test-aux-functions ${THIS_SH} -c '{ time; echo after; }' |& wc -l | _cut_leading_spaces diff --git a/tests/procsub.tests b/tests/procsub.tests index 946d2c22..140f6e70 100644 --- a/tests/procsub.tests +++ b/tests/procsub.tests @@ -12,7 +12,7 @@ # along with this program. If not, see . # # process substitution constructs that have caused problems in the past -. ./test-glue-functions +. ./test-aux-functions eval cat <(echo test1) eval "echo foo;cat" <(echo test2) diff --git a/tests/test-aux-functions b/tests/test-aux-functions new file mode 100644 index 00000000..2423eebb --- /dev/null +++ b/tests/test-aux-functions @@ -0,0 +1,21 @@ +# 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' +} + +test_runsub() +{ + scriptname=${1##*/} + printf '\t%s\n' "${scriptname}" + + ${THIS_SH} "$1" +} diff --git a/tests/unicode2.sub b/tests/unicode2.sub index 16dd604a..b98ac7c4 100644 --- a/tests/unicode2.sub +++ b/tests/unicode2.sub @@ -11,7 +11,7 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . # -. ./test-glue-functions +. ./test-aux-functions export LANG=en_US.UTF-8 diff --git a/variables.h b/variables.h index f098cce1..5e870986 100644 --- a/variables.h +++ b/variables.h @@ -173,6 +173,8 @@ typedef struct _vlist { #define tempvar_p(var) ((((var)->attributes) & (att_tempvar))) #define propagate_p(var) ((((var)->attributes) & (att_propagate))) +#define assigning_p(var) ((((var)->attributes) & (att_assigning))) + /* Variable names: lvalues */ #define name_cell(var) ((var)->name)