diff options
Diffstat (limited to 'debian/patches/bash52-015.diff')
-rw-r--r-- | debian/patches/bash52-015.diff | 169 |
1 files changed, 169 insertions, 0 deletions
diff --git a/debian/patches/bash52-015.diff b/debian/patches/bash52-015.diff new file mode 100644 index 0000000..c4ccaf0 --- /dev/null +++ b/debian/patches/bash52-015.diff @@ -0,0 +1,169 @@ + BASH PATCH REPORT + ================= + +Bash-Release: 5.2 +Patch-ID: bash52-015 + +Bug-Reported-by: Frode Nordahl <frode.nordahl@canonical.com> +Bug-Reference-ID: <20221119070714.351759-1-frode.nordahl@canonical.com> +Bug-Reference-URL: https://lists.gnu.org/archive/html/bug-bash/2022-11/msg00078.html + +Bug-Description: + +There are several cases where bash is too aggressive when optimizing out forks +in subshells. For example, `eval' and traps should never be optimized. + +--- a/builtins/common.h ++++ b/builtins/common.h +@@ -51,6 +51,7 @@ do { \ + #define SEVAL_FUNCDEF 0x080 /* only allow function definitions */ + #define SEVAL_ONECMD 0x100 /* only allow a single command */ + #define SEVAL_NOHISTEXP 0x200 /* inhibit history expansion */ ++#define SEVAL_NOOPTIMIZE 0x400 /* don't try to set optimization flags */ + + /* Flags for describe_command, shared between type.def and command.def */ + #define CDESC_ALL 0x001 /* type -a */ +--- a/builtins/eval.def ++++ b/builtins/eval.def +@@ -53,5 +53,5 @@ eval_builtin (list) + return (EX_USAGE); + list = loptend; /* skip over possible `--' */ + +- return (list ? evalstring (string_list (list), "eval", SEVAL_NOHIST) : EXECUTION_SUCCESS); ++ return (list ? evalstring (string_list (list), "eval", SEVAL_NOHIST|SEVAL_NOOPTIMIZE) : EXECUTION_SUCCESS); + } +--- a/builtins/evalstring.c ++++ b/builtins/evalstring.c +@@ -132,8 +132,8 @@ optimize_connection_fork (command) + if (command->type == cm_connection && + (command->value.Connection->connector == AND_AND || command->value.Connection->connector == OR_OR || command->value.Connection->connector == ';') && + (command->value.Connection->second->flags & CMD_TRY_OPTIMIZING) && +- ((startup_state == 2 && should_suppress_fork (command->value.Connection->second)) || +- ((subshell_environment & SUBSHELL_PAREN) && should_optimize_fork (command->value.Connection->second, 0)))) ++ (should_suppress_fork (command->value.Connection->second) || ++ ((subshell_environment & SUBSHELL_PAREN) && should_optimize_fork (command->value.Connection->second, 0)))) + { + command->value.Connection->second->flags |= CMD_NO_FORK; + command->value.Connection->second->value.Simple->flags |= CMD_NO_FORK; +@@ -290,6 +290,7 @@ parse_prologue (string, flags, tag) + (flags & SEVAL_NOFREE) -> don't free STRING when finished + (flags & SEVAL_RESETLINE) -> reset line_number to 1 + (flags & SEVAL_NOHISTEXP) -> history_expansion_inhibited -> 1 ++ (flags & SEVAL_NOOPTIMIZE) -> don't try to turn on optimizing flags + */ + + int +@@ -502,7 +503,9 @@ parse_and_execute (string, from_file, fl + if we are at the end of the command string, the last in a + series of connection commands is + command->value.Connection->second. */ +- else if (command->type == cm_connection && can_optimize_connection (command)) ++ else if (command->type == cm_connection && ++ (flags & SEVAL_NOOPTIMIZE) == 0 && ++ can_optimize_connection (command)) + { + command->value.Connection->second->flags |= CMD_TRY_OPTIMIZING; + command->value.Connection->second->value.Simple->flags |= CMD_TRY_OPTIMIZING; +--- a/execute_cmd.c ++++ b/execute_cmd.c +@@ -1654,7 +1654,8 @@ execute_in_subshell (command, asynchrono + subshell sets an exit trap, so we set CMD_NO_FORK for simple commands + and set CMD_TRY_OPTIMIZING for simple commands on the right side of an + and-or or `;' list to test for optimizing forks when they are executed. */ +- if (user_subshell && command->type == cm_subshell) ++ if (user_subshell && command->type == cm_subshell && ++ (command->flags & (CMD_TIME_PIPELINE|CMD_INVERT_RETURN)) == 0) + optimize_subshell_command (command->value.Subshell->command); + + /* Do redirections, then dispose of them before recursive call. */ +--- a/jobs.c ++++ b/jobs.c +@@ -4220,7 +4220,7 @@ run_sigchld_trap (nchild) + jobs_list_frozen = 1; + for (i = 0; i < nchild; i++) + { +- parse_and_execute (savestring (trap_command), "trap", SEVAL_NOHIST|SEVAL_RESETLINE); ++ parse_and_execute (savestring (trap_command), "trap", SEVAL_NOHIST|SEVAL_RESETLINE|SEVAL_NOOPTIMIZE); + } + + run_unwind_frame ("SIGCHLD trap"); +--- a/parse.y ++++ b/parse.y +@@ -2827,7 +2827,7 @@ execute_variable_command (command, vname + if (last_lastarg) + last_lastarg = savestring (last_lastarg); + +- parse_and_execute (savestring (command), vname, SEVAL_NONINT|SEVAL_NOHIST); ++ parse_and_execute (savestring (command), vname, SEVAL_NONINT|SEVAL_NOHIST|SEVAL_NOOPTIMIZE); + + restore_parser_state (&ps); + bind_variable ("_", last_lastarg, 0); +--- a/patchlevel.h ++++ b/patchlevel.h +@@ -25,6 +25,6 @@ + regexp `^#define[ ]*PATCHLEVEL', since that's what support/mkversion.sh + looks for to find the patch level (for the sccs version string). */ + +-#define PATCHLEVEL 14 ++#define PATCHLEVEL 15 + + #endif /* _PATCHLEVEL_H_ */ +--- a/trap.c ++++ b/trap.c +@@ -304,6 +304,7 @@ run_pending_traps () + sh_parser_state_t pstate; + volatile int save_return_catch_flag, function_code; + procenv_t save_return_catch; ++ char *trap_command, *old_trap; + #if defined (ARRAY_VARS) + ARRAY *ps; + #endif +@@ -419,6 +420,9 @@ run_pending_traps () + } + else + { ++ old_trap = trap_list[sig]; ++ trap_command = savestring (old_trap); ++ + save_parser_state (&pstate); + save_subst_varlist = subst_assign_varlist; + subst_assign_varlist = 0; +@@ -441,7 +445,8 @@ run_pending_traps () + } + + if (function_code == 0) +- x = parse_and_execute (savestring (trap_list[sig]), "trap", SEVAL_NONINT|SEVAL_NOHIST|SEVAL_RESETLINE); ++ /* XXX is x always last_command_exit_value? */ ++ x = parse_and_execute (trap_command, "trap", SEVAL_NONINT|SEVAL_NOHIST|SEVAL_RESETLINE|SEVAL_NOOPTIMIZE); + else + { + parse_and_execute_cleanup (sig + 1); /* XXX - could use -1 */ +@@ -1002,7 +1007,7 @@ run_exit_trap () + if (code == 0 && function_code == 0) + { + reset_parser (); +- parse_and_execute (trap_command, "exit trap", SEVAL_NONINT|SEVAL_NOHIST|SEVAL_RESETLINE); ++ parse_and_execute (trap_command, "exit trap", SEVAL_NONINT|SEVAL_NOHIST|SEVAL_RESETLINE|SEVAL_NOOPTIMIZE); + } + else if (code == ERREXIT) + retval = last_command_exit_value; +@@ -1109,7 +1114,7 @@ _run_trap_internal (sig, tag) + function_code = setjmp_nosigs (return_catch); + } + +- flags = SEVAL_NONINT|SEVAL_NOHIST; ++ flags = SEVAL_NONINT|SEVAL_NOHIST|SEVAL_NOOPTIMIZE; + if (sig != DEBUG_TRAP && sig != RETURN_TRAP && sig != ERROR_TRAP) + flags |= SEVAL_RESETLINE; + evalnest++; +--- a/y.tab.c ++++ b/y.tab.c +@@ -5138,7 +5138,7 @@ execute_variable_command (command, vname + if (last_lastarg) + last_lastarg = savestring (last_lastarg); + +- parse_and_execute (savestring (command), vname, SEVAL_NONINT|SEVAL_NOHIST); ++ parse_and_execute (savestring (command), vname, SEVAL_NONINT|SEVAL_NOHIST|SEVAL_NOOPTIMIZE); + + restore_parser_state (&ps); + bind_variable ("_", last_lastarg, 0); |