change to readline callback signal handling; fix message when popping shell function context; handle new terminating signals inside terminating signal handler; fix to pattern substitution with null replacement and null string; fix to alias expansion when we get a SIGINT while entering a command substitution in an interactive shell

This commit is contained in:
Chet Ramey
2022-10-15 13:34:51 -04:00
parent 55a8311420
commit 055a4552c9
15 changed files with 139 additions and 24 deletions
+66
View File
@@ -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 <kirelagin@gmail.com>
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 <simon.marchi@polymtl.ca>
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 <xavier.delaruelle@gmail.com>
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 <schwab@suse.de>
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) <callek@gmail.com>
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 <fengxj325@gmail.com>
- parse_string_to_word_list,parse_string_to_command: make sure to set
PST_STRING in parser_flags since we're resetting expand_aliases
+2
View File
@@ -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;
+1
View File
@@ -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)
+14 -4
View File
@@ -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));
}
+2 -1
View File
@@ -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)
{
+5 -3
View File
@@ -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;
}
}
+4 -1
View File
@@ -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
+4 -1
View File
@@ -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)
+1
View File
@@ -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 {
+5 -5
View File
@@ -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? */
+24 -6
View File
@@ -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
+3 -2
View File
@@ -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';
Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

+5
View File
@@ -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
+3 -1
View File
@@ -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;
}