From 3b1164fc6937aaf25d43ce286d8387ea75c38a1d Mon Sep 17 00:00:00 2001 From: Chet Ramey Date: Mon, 12 Oct 2015 10:04:55 -0400 Subject: [PATCH] commit bash-20151009 snapshot --- CWRU/CWRU.chlog | 31 +++++++++++++++++++++++++++++++ arrayfunc.c | 2 ++ bashjmp.h | 2 ++ execute_cmd.c | 1 - expr.c | 3 +++ subst.c | 19 +++++++++++-------- variables.c | 7 +++++++ 7 files changed, 56 insertions(+), 9 deletions(-) diff --git a/CWRU/CWRU.chlog b/CWRU/CWRU.chlog index 77e40f87..f02d1e89 100644 --- a/CWRU/CWRU.chlog +++ b/CWRU/CWRU.chlog @@ -9719,3 +9719,34 @@ subst.c bug reported by Daniel Colascione - char_is_quoted: make analogous changes to handle $'...' so we can accommodate $'ab \' cd' + + 10/11 + ----- +subst.c,bashjmp.h + - no_longjmp_on_fatal_error: now global so other parts of the shell can + use it + +arrayfunc.c + - expand_array_index: if no_longjmp_on_fatal_error is non-zero, don't + longjmp to top_level, just return 0. Fixes bug reported by + isabella parakiss + +subst.c + - CQ_RETURN: restore old value of no_longjmp_on_fatal_error (oldjmp); + make sure all callers (skip_matched_pair, skip_to_delim, + char_is_quoted) save no_longjmp_on_fatal_error to oldjmp before + setting it to 1 + +expr.c + - expr_streval: if longjmping after an unbound variable error, jump + back to expr toplevel (evalbuf) if no_longjmp_on_fatal_error is set + in an interactive shell + +variables.c + - push_func_var: if pushing an array variable, such as when a variable + in the temporary environment is promoted to an array by mapfile when + the shell is in posix mode (so variable assignments preceding special + builtins or shell functions persist in the shell environment after + the builtin returns), make sure to copy the array or hash table so + the variable is duplicated correctly. Fixes seg fault reported by + Linda Walsh diff --git a/arrayfunc.c b/arrayfunc.c index 6479aaaf..c5a80bad 100644 --- a/arrayfunc.c +++ b/arrayfunc.c @@ -902,6 +902,8 @@ array_expand_index (var, s, len) { last_command_exit_value = EXECUTION_FAILURE; + if (no_longjmp_on_fatal_error) + return 0; top_level_cleanup (); jump_to_top_level (DISCARD); } diff --git a/bashjmp.h b/bashjmp.h index d6b6611c..79152fe5 100644 --- a/bashjmp.h +++ b/bashjmp.h @@ -27,6 +27,8 @@ extern procenv_t top_level; extern procenv_t subshell_top_level; extern procenv_t return_catch; /* used by `return' builtin */ +extern int no_longjmp_on_fatal_error; + #define SHFUNC_RETURN() sh_longjmp (return_catch, 1) #define COPY_PROCENV(old, save) \ diff --git a/execute_cmd.c b/execute_cmd.c index daa08c23..2288b165 100644 --- a/execute_cmd.c +++ b/execute_cmd.c @@ -4444,7 +4444,6 @@ execute_builtin (builtin, words, flags, subshell) sourcenest++; /* execute_subshell_builtin_or_function sets this to 0 */ } - /* `return' does a longjmp() back to a saved environment in execute_function. If a variable assignment list preceded the command, and the shell is running in POSIX mode, we need to merge that into the shell_variables diff --git a/expr.c b/expr.c index ce6c0bde..1ddb693c 100644 --- a/expr.c +++ b/expr.c @@ -1123,6 +1123,9 @@ expr_streval (tok, e, lvalue) FREE (value); /* array_variable_name returns new memory */ #endif + if (no_longjmp_on_fatal_error && interactive_shell) + sh_longjmp (evalbuf, 1); + if (interactive_shell) { expr_unwind (); diff --git a/subst.c b/subst.c index 80f9fd9e..2a7366ff 100644 --- a/subst.c +++ b/subst.c @@ -159,6 +159,10 @@ int assigning_in_environment; SIGCHLD trap and so it can be saved and restored by the trap handlers. */ WORD_LIST *subst_assign_varlist = (WORD_LIST *)NULL; +/* Tell the expansion functions to not longjmp back to top_level on fatal + errors. Enabled when doing completion and prompt string expansion. */ +int no_longjmp_on_fatal_error = 0; + /* Extern functions and variables from different files. */ extern int last_command_exit_value, last_command_exit_signal; extern int subshell_environment, line_number; @@ -205,10 +209,6 @@ static WORD_DESC expand_wdesc_error, expand_wdesc_fatal; static char expand_param_error, expand_param_fatal; static char extract_string_error, extract_string_fatal; -/* Tell the expansion functions to not longjmp back to top_level on fatal - errors. Enabled when doing completion and prompt string expansion. */ -static int no_longjmp_on_fatal_error = 0; - /* Set by expand_word_unsplit; used to inhibit splitting and re-joining $* on $IFS, primarily when doing assignment statements. */ static int expand_no_split_dollar_star = 0; @@ -1639,7 +1639,7 @@ unquote_bang (string) } #endif -#define CQ_RETURN(x) do { no_longjmp_on_fatal_error = 0; return (x); } while (0) +#define CQ_RETURN(x) do { no_longjmp_on_fatal_error = oldjmp; return (x); } while (0) /* This function assumes s[i] == open; returns with s[ret] == close; used to parse array subscripts. FLAGS & 1 means to not attempt to skip over @@ -1651,12 +1651,13 @@ skip_matched_pair (string, start, open, close, flags) const char *string; int start, open, close, flags; { - int i, pass_next, backq, si, c, count; + int i, pass_next, backq, si, c, count, oldjmp; size_t slen; char *temp, *ss; DECLARE_MBSTATE; slen = strlen (string + start) + start; + oldjmp = no_longjmp_on_fatal_error; no_longjmp_on_fatal_error = 1; i = start + 1; /* skip over leading bracket */ @@ -1758,13 +1759,14 @@ skip_to_delim (string, start, delims, flags) char *delims; int flags; { - int i, pass_next, backq, dquote, si, c; + int i, pass_next, backq, dquote, si, c, oldjmp; int invert, skipquote, skipcmd, noprocsub, completeflag, histexp; size_t slen; char *temp, open[3]; DECLARE_MBSTATE; slen = strlen (string + start) + start; + oldjmp = no_longjmp_on_fatal_error; if (flags & SD_NOJMP) no_longjmp_on_fatal_error = 1; invert = (flags & SD_INVERT); @@ -1925,11 +1927,12 @@ char_is_quoted (string, eindex) char *string; int eindex; { - int i, pass_next, c; + int i, pass_next, c, oldjmp; size_t slen; DECLARE_MBSTATE; slen = strlen (string); + oldjmp = no_longjmp_on_fatal_error; no_longjmp_on_fatal_error = 1; i = pass_next = 0; while (i <= eindex) diff --git a/variables.c b/variables.c index 80d125df..73f69c79 100644 --- a/variables.c +++ b/variables.c @@ -4446,6 +4446,13 @@ push_func_var (data) shell_variables->table = hash_create (VARIABLES_HASH_BUCKETS); /* XXX - should we set v->context here? */ v = bind_variable_internal (var->name, value_cell (var), shell_variables->table, 0, 0); +#if defined (ARRAY_VARS) + if (array_p (var) || assoc_p (var)) + { + FREE (value_cell (v)); + var_setvalue (v, array_p (var) ? array_copy (array_cell (var)) : assoc_copy (assoc_cell (var))); + } +#endif if (shell_variables == global_variables) var->attributes &= ~(att_tempvar|att_propagate); else