summaryrefslogtreecommitdiffstats
path: root/debian/patches/bash52-015.diff
diff options
context:
space:
mode:
Diffstat (limited to 'debian/patches/bash52-015.diff')
-rw-r--r--debian/patches/bash52-015.diff169
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);