diff --git a/CWRU/CWRU.chlog b/CWRU/CWRU.chlog index b04fb256..68a7d35d 100644 --- a/CWRU/CWRU.chlog +++ b/CWRU/CWRU.chlog @@ -4078,3 +4078,69 @@ execute_cmd.c - shell_execve: rearrange code so that we check for a bad interpreter before printing a generic ENOENT error message. Report from Kirill Elagin + + 10/12 + ----- +lib/readline/callback.c + - CALLBACK_READ_RETURN: add an inlined call to RL_CHECK_SIGNALS so we + can handle any signals that arrived before we restored the calling + application's signal handlers. From a gdb dicussion with + Simon Marchi + + 10/12 + ----- +variables.c + - pop_var_context: flag an internal error for shell_variables not + pointing to a function context only if we haven't already flushed + all the local contexts and reset variable_context. This can happen + if errexit is enabled and we're going to be exiting the shell, but + we're running unwind-protects on our way out. Report from + Xavier Delaruelle + + 10/13 + ----- +sig.c + - kill_shell: broke the code that resets the signal disposition to the + default and sends a terminating signal to the shell into a separate + function + - termsig_handler: set handling_termsig to terminating_signal and make + it file-scope so other functions know we're handling a terminating + signal and are about to exit, and which signal it is (latter not used + yet) + - termsig_sighandler: if we get a fatal signal while we're handling a + fatal signal, kill ourselves with the second fatal signal immediately. + Fixes issue reported by Andreas Schwab + +execute_cmd.c + - execute_case_command: call CHECK_TERMSIG after the call to strmatch, + since gmatch will return FNM_NOMATCH if there's a pending terminating + signal and we don't want incorrect results + +subst.c + - pat_subst: make sure REP is non-NULL before calling savestring on it. + Report from Justin Wood (Callek) + + 10/14 + ----- +builtins/{shopt.def,common.h} + - expand_aliases: split into a variable that holds the current state + of alias expansion (expand_aliases) and a variable that reflects the + global option value (expalias_flag), make sure expand_aliases is set + appropriately by shopt + +shell.c,execute_cmd.c,general.c + - expand_aliases: make sure expand_aliases and expalias_flag always + agree + +parser.h + - PST_STRING: new parser flag, set when parsing a string to a command + or word list + +parse.y + - reset_parser: if we're parsing a command substitution or a string, + and need to restore expand_aliases, make sure it's set to the value + of expalias_flag. + Fixes SIGINT during interactive command substitution parsing bug + reported by feng xiangjun + - parse_string_to_word_list,parse_string_to_command: make sure to set + PST_STRING in parser_flags since we're resetting expand_aliases diff --git a/builtins/common.h b/builtins/common.h index 543e4e0c..726bd91f 100644 --- a/builtins/common.h +++ b/builtins/common.h @@ -261,6 +261,8 @@ extern int expand_once_flag; extern int extglob_flag; #endif +extern int expaliases_flag; + /* variables from source.def */ extern int source_searches_cwd; extern int source_uses_path; diff --git a/builtins/evalstring.c b/builtins/evalstring.c index fd635299..a4c263fd 100644 --- a/builtins/evalstring.c +++ b/builtins/evalstring.c @@ -590,6 +590,7 @@ parse_string (string, from_file, flags, cmdp, endp) char *ostring; volatile sigset_t ps_sigmask; + /* unwind-protects common to this and parse_and_execute */ parse_prologue (string, flags, PS_TAG); #if defined (HAVE_POSIX_SIGNALS) diff --git a/builtins/shopt.def b/builtins/shopt.def index 0a6a9b74..0c9de8e6 100644 --- a/builtins/shopt.def +++ b/builtins/shopt.def @@ -154,6 +154,9 @@ int extglob_flag = EXTGLOB_DEFAULT; static int shopt_set_extglob PARAMS((char *, int)); #endif +int expaliases_flag = 0; +static int shopt_set_expaliases PARAMS((char *, int)); + static int shopt_set_debug_mode PARAMS((char *, int)); static int shopt_login_shell; @@ -203,7 +206,7 @@ static struct { #endif { "dotglob", &glob_dot_filenames, (shopt_set_func_t *)NULL }, { "execfail", &no_exit_on_failed_exec, (shopt_set_func_t *)NULL }, - { "expand_aliases", &expand_aliases, (shopt_set_func_t *)NULL }, + { "expand_aliases", &expaliases_flag, shopt_set_expaliases }, #if defined (DEBUGGER) { "extdebug", &debugging_mode, shopt_set_debug_mode }, #endif @@ -355,7 +358,7 @@ reset_shopt_options () check_window_size = CHECKWINSIZE_DEFAULT; allow_null_glob_expansion = glob_dot_filenames = 0; no_exit_on_failed_exec = 0; - expand_aliases = 0; + expand_aliases = expaliases_flag = 0; extended_quote = 1; fail_glob_expansion = 0; glob_asciirange = GLOBASCII_DEFAULT; @@ -636,6 +639,15 @@ shopt_set_debug_mode (option_name, mode) return (0); } +static int +shopt_set_expaliases (option_name, mode) + char *option_name; + int mode; +{ + expand_aliases = expaliases_flag; + return 0; +} + #if defined (EXTENDED_GLOB) static int shopt_set_extglob (option_name, mode) @@ -652,8 +664,6 @@ static int shopt_enable_hostname_completion (option_name, mode) char *option_name; int mode; - - { return (enable_hostname_completion (mode)); } diff --git a/execute_cmd.c b/execute_cmd.c index abb19b73..b1066451 100644 --- a/execute_cmd.c +++ b/execute_cmd.c @@ -1539,7 +1539,7 @@ execute_in_subshell (command, asynchronous, pipe_in, pipe_out, fds_to_close) expansion with `shopt -s expand_alias' to continue to expand aliases. */ if (ois != interactive_shell) - expand_aliases = 0; + expand_aliases = expaliases_flag = 0; } /* Subshells are neither login nor interactive. */ @@ -3627,6 +3627,7 @@ execute_case_command (case_command) free (pattern); dispose_words (es); + CHECK_TERMSIG; if (match) { diff --git a/general.c b/general.c index 85c5a8b6..2bc9f382 100644 --- a/general.c +++ b/general.c @@ -91,7 +91,7 @@ static struct { { &interactive_comments, &source_uses_path, - &expand_aliases, + &expaliases_flag, &inherit_errexit, &print_shift_error, 0 @@ -106,7 +106,8 @@ posix_initialize (on) /* Things that should be turned on when posix mode is enabled. */ if (on != 0) { - interactive_comments = source_uses_path = expand_aliases = 1; + interactive_comments = source_uses_path = 1; + expand_aliases = expaliases_flag = 1; inherit_errexit = 1; source_searches_cwd = 0; print_shift_error = 1; @@ -116,13 +117,14 @@ posix_initialize (on) else if (saved_posix_vars) /* on == 0, restore saved settings */ { set_posix_options (saved_posix_vars); + expand_aliases = expaliases_flag; free (saved_posix_vars); saved_posix_vars = 0; } else /* on == 0, restore a default set of settings */ { source_searches_cwd = 1; - expand_aliases = interactive_shell; + expand_aliases = expaliases_flag = interactive_shell; /* XXX */ print_shift_error = 0; } } diff --git a/lib/readline/callback.c b/lib/readline/callback.c index 69df77df..d78a7ca7 100644 --- a/lib/readline/callback.c +++ b/lib/readline/callback.c @@ -115,7 +115,10 @@ rl_callback_handler_install (const char *prompt, rl_vcpfunc_t *linefunc) #define CALLBACK_READ_RETURN() \ do { \ if (rl_persistent_signal_handlers == 0) \ - rl_clear_signals (); \ + { \ + rl_clear_signals (); \ + if (_rl_caught_signal) _rl_signal_handler (_rl_caught_signal); \ + } \ return; \ } while (0) #else diff --git a/parse.y b/parse.y index 75904eea..07d788b4 100644 --- a/parse.y +++ b/parse.y @@ -3306,6 +3306,8 @@ reset_parser () if (parser_state & (PST_EXTPAT|PST_CMDSUBST)) extended_glob = extglob_flag; #endif + if (parser_state & (PST_CMDSUBST|PST_STRING)) + expand_aliases = expaliases_flag; parser_state = 0; here_doc_first_line = 0; @@ -4392,6 +4394,7 @@ parse_string_to_command (string, flags) if (flags & SX_COMPLETE) parser_state |= PST_NOERROR; + parser_state |= PST_STRING; expand_aliases = 0; cmd = 0; @@ -6409,7 +6412,7 @@ parse_string_to_word_list (s, flags, whom) /* State flags we don't want to persist into compound assignments. */ parser_state &= ~PST_NOEXPAND; /* parse_comsub sentinel */ /* State flags we want to set for this run through the tokenizer. */ - parser_state |= PST_COMPASSIGN|PST_REPARSE; + parser_state |= PST_COMPASSIGN|PST_REPARSE|PST_STRING; } while ((tok = read_token (READ)) != yacc_EOF) diff --git a/parser.h b/parser.h index 59bf0fec..cae3a35f 100644 --- a/parser.h +++ b/parser.h @@ -50,6 +50,7 @@ #define PST_ENDALIAS 0x200000 /* just finished expanding and consuming an alias */ #define PST_NOEXPAND 0x400000 /* don't expand anything in read_token_word; for command substitution */ #define PST_NOERROR 0x800000 /* don't print error messages in yyerror */ +#define PST_STRING 0x1000000 /* parsing a string to a command or word list */ /* Definition of the delimiter stack. Needed by parse.y and bashhist.c. */ struct dstack { diff --git a/shell.c b/shell.c index ee9d445d..ebd89651 100644 --- a/shell.c +++ b/shell.c @@ -1844,8 +1844,8 @@ reset_option_defaults () static void init_interactive () { - expand_aliases = interactive_shell = startup_state = 1; - interactive = 1; + expand_aliases = expaliases_flag = 1; + interactive_shell = startup_state = interactive = 1; #if defined (HISTORY) if (enable_history_list == -1) enable_history_list = 1; /* set default */ @@ -1865,7 +1865,7 @@ init_noninteractive () bash_history_reinit (0); #endif /* HISTORY */ interactive_shell = startup_state = interactive = 0; - expand_aliases = posixly_correct; /* XXX - was 0 not posixly_correct */ + expand_aliases = expaliases_flag = posixly_correct; /* XXX - was 0 not posixly_correct */ no_line_editing = 1; #if defined (JOB_CONTROL) /* Even if the shell is not interactive, enable job control if the -i or @@ -1882,7 +1882,7 @@ init_interactive_script () enable_history_list = 1; #endif init_noninteractive (); - expand_aliases = interactive_shell = startup_state = 1; + expand_aliases = expaliases_flag = interactive_shell = startup_state = 1; #if defined (HISTORY) remember_on_history = enable_history_list; /* XXX */ #endif @@ -2025,7 +2025,7 @@ shell_reinitialize () debugging = do_version = line_number = last_command_exit_value = 0; forced_interactive = interactive_shell = 0; subshell_environment = running_in_background = 0; - expand_aliases = 0; + expand_aliases = expaliases_flag = 0; bash_argv_initialized = 0; /* XXX - should we set jobs_m_flag to 0 here? */ diff --git a/sig.c b/sig.c index 840d5775..0d31cb4f 100644 --- a/sig.c +++ b/sig.c @@ -94,6 +94,7 @@ static SigHandler *old_winch = (SigHandler *)SIG_DFL; #endif static void initialize_shell_signals PARAMS((void)); +static void kill_shell PARAMS((int)); void initialize_signals (reinit) @@ -486,6 +487,8 @@ restore_sigmask () #endif } +static int handling_termsig = 0; + sighandler termsig_sighandler (sig) int sig; @@ -532,6 +535,14 @@ termsig_sighandler (sig) sig == terminating_signal) terminate_immediately = 1; + /* If we are currently handling a terminating signal, we have a couple of + choices here. We can ignore this second terminating signal and let the + shell exit from the first one, or we can exit immediately by killing + the shell with this signal. This code implements the latter; to implement + the former, replace the kill_shell(sig) with return. */ + if (handling_termsig) + kill_shell (sig); /* just short-circuit now */ + terminating_signal = sig; if (terminate_immediately) @@ -564,16 +575,13 @@ void termsig_handler (sig) int sig; { - static int handling_termsig = 0; - int i, core; - sigset_t mask; - /* Simple semaphore to keep this function from being executed multiple times. Since we no longer are running as a signal handler, we don't block multiple occurrences of the terminating signals while running. */ if (handling_termsig) return; - handling_termsig = 1; + + handling_termsig = terminating_signal; /* for termsig_sighandler */ terminating_signal = 0; /* keep macro from re-testing true. */ /* I don't believe this condition ever tests true. */ @@ -613,6 +621,16 @@ termsig_handler (sig) run_exit_trap (); /* XXX - run exit trap possibly in signal context? */ + kill_shell (sig); +} + +static void +kill_shell (sig) + int sig; +{ + int i, core; + sigset_t mask; + /* We don't change the set of blocked signals. If a user starts the shell with a terminating signal blocked, we won't get here (and if by some magic chance we do, we'll exit below). What we do is to restore the @@ -627,7 +645,7 @@ termsig_handler (sig) if (dollar_dollar_pid != 1) exit (128+sig); /* just in case the kill fails? */ - /* We get here only under extraordinary circumstances. */ + /* We get here only under extraordinarily rare circumstances. */ /* We are PID 1, and the kill above failed to kill the process. We assume this means that we are running as an init process in a pid namespace diff --git a/subst.c b/subst.c index 51fd6468..b778526a 100644 --- a/subst.c +++ b/subst.c @@ -4005,7 +4005,7 @@ expand_string_for_patsub (string, quoted) if (value) { t = (value->next) ? string_list (value) : value->word->word; - ret = quote_string_for_repl (t, quoted); + ret = t ? quote_string_for_repl (t, quoted) : t; if (t != value->word->word) free (t); dispose_words (value); @@ -8970,7 +8970,8 @@ pat_subst (string, pat, rep, mflags) return (ret); } else if (*string == 0 && (match_pattern (string, pat, mtype, &s, &e) != 0)) - return ((mflags & MATCH_EXPREP) ? strcreplace (rep, '&', "", 2) : savestring (rep)); + return (mflags & MATCH_EXPREP) ? strcreplace (rep, '&', "", 2) + : (rep ? savestring (rep) : savestring ("")); ret = (char *)xmalloc (rsize = 64); ret[0] = '\0'; diff --git a/support/bash-logo-web.png b/support/bash-logo-web.png new file mode 100644 index 00000000..e8744fe9 Binary files /dev/null and b/support/bash-logo-web.png differ diff --git a/tests/extglob.tests b/tests/extglob.tests index f13e8fb6..ef5d7793 100644 --- a/tests/extglob.tests +++ b/tests/extglob.tests @@ -379,6 +379,11 @@ shopt -u globstar # in the right place builtin cd "$MYDIR" +# seg fault in bash-5.2 +foo= +foo=${foo/#*([.])} +unset foo + ${THIS_SH} ./extglob1.sub ${THIS_SH} ./extglob1a.sub ${THIS_SH} ./extglob3.sub diff --git a/variables.c b/variables.c index 1a0c2c45..84af3c63 100644 --- a/variables.c +++ b/variables.c @@ -5413,7 +5413,9 @@ pop_var_context () vcxt = shell_variables; if (vc_isfuncenv (vcxt) == 0) { - internal_error (_("pop_var_context: head of shell_variables not a function context")); + /* If we haven't flushed all of the local contexts already, flag an error */ + if (shell_variables != global_variables || variable_context > 0) + internal_error (_("pop_var_context: head of shell_variables not a function context")); return; }