diff --git a/bash-5.2-patch-3.patch b/bash-5.2-patch-3.patch new file mode 100644 index 0000000..e8b2c55 --- /dev/null +++ b/bash-5.2-patch-3.patch @@ -0,0 +1,60 @@ +diff --git a/patchlevel.h b/patchlevel.h +--- 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 2 ++#define PATCHLEVEL 3 + + #endif /* _PATCHLEVEL_H_ */ +diff --git a/print_cmd.c b/print_cmd.c +--- a/print_cmd.c ++++ b/print_cmd.c +@@ -297,10 +297,12 @@ make_command_string_internal (command) + case '\n': /* special case this */ + { + char c = command->value.Connection->connector; ++ int was_newline; + + s[0] = printing_comsub ? c : ';'; + s[1] = '\0'; + ++ was_newline = deferred_heredocs == 0 && was_heredoc == 0 && c == '\n'; + if (deferred_heredocs == 0) + { + if (was_heredoc == 0) +@@ -314,6 +316,8 @@ make_command_string_internal (command) + + if (inside_function_def) + cprintf ("\n"); ++ else if (printing_comsub && c == '\n' && was_newline == 0) ++ cprintf ("\n"); /* preserve newlines in comsubs but don't double them */ + else + { + if (c == ';') +@@ -1365,7 +1369,11 @@ print_function_def (func) + cmdcopy->redirects = func_redirects; + } + else +- newline ("}"); ++ { ++ /* { */ ++ newline ("}"); ++ was_heredoc = 0; /* not printing any here-documents now */ ++ } + + dispose_command (cmdcopy); + } +@@ -1442,7 +1450,10 @@ named_function_string (name, command, flags) + cmdcopy->redirects = func_redirects; + } + else +- newline ("}"); ++ { /* { */ ++ newline ("}"); ++ was_heredoc = 0; ++ } + + result = the_printed_command; diff --git a/bash-5.2-nested-expansion.patch b/bash-5.2-patch-4.patch similarity index 68% rename from bash-5.2-nested-expansion.patch rename to bash-5.2-patch-4.patch index a8d4ec1..5cf7111 100644 --- a/bash-5.2-nested-expansion.patch +++ b/bash-5.2-patch-4.patch @@ -1,7 +1,18 @@ +diff --git a/patchlevel.h b/patchlevel.h +--- 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 3 ++#define PATCHLEVEL 4 + + #endif /* _PATCHLEVEL_H_ */ diff --git a/subst.c b/subst.c --- a/subst.c +++ b/subst.c -@@ -1803,6 +1803,9 @@ extract_heredoc_dolbrace_string (string, sindex, quoted, flags) +@@ -1798,6 +1798,9 @@ extract_heredoc_dolbrace_string (string, sindex, quoted, flags) return (result); } @@ -11,7 +22,7 @@ diff --git a/subst.c b/subst.c /* Extract a parameter expansion expression within ${ and } from STRING. Obey the Posix.2 rules for finding the ending `}': count braces while skipping over enclosed quoted strings and command substitutions. -@@ -1833,6 +1836,8 @@ extract_dollar_brace_string (string, sindex, quoted, flags) +@@ -1828,6 +1831,8 @@ extract_dollar_brace_string (string, sindex, quoted, flags) if (quoted == Q_HERE_DOCUMENT && dolbrace_state == DOLBRACE_QUOTE && (flags & SX_NOALLOC) == 0) return (extract_heredoc_dolbrace_string (string, sindex, quoted, flags)); @@ -20,7 +31,7 @@ diff --git a/subst.c b/subst.c pass_character = 0; nesting_level = 1; slen = strlen (string + *sindex) + *sindex; -@@ -1857,6 +1862,8 @@ extract_dollar_brace_string (string, sindex, quoted, flags) +@@ -1852,6 +1857,8 @@ extract_dollar_brace_string (string, sindex, quoted, flags) if (string[i] == '$' && string[i+1] == LBRACE) { @@ -29,7 +40,7 @@ diff --git a/subst.c b/subst.c nesting_level++; i += 2; if (dolbrace_state == DOLBRACE_QUOTE || dolbrace_state == DOLBRACE_WORD) -@@ -1869,6 +1876,7 @@ extract_dollar_brace_string (string, sindex, quoted, flags) +@@ -1864,6 +1871,7 @@ extract_dollar_brace_string (string, sindex, quoted, flags) nesting_level--; if (nesting_level == 0) break; diff --git a/bash-5.2-patch-5.patch b/bash-5.2-patch-5.patch new file mode 100644 index 0000000..e45ae56 --- /dev/null +++ b/bash-5.2-patch-5.patch @@ -0,0 +1,24 @@ +diff --git a/patchlevel.h b/patchlevel.h +--- 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 4 ++#define PATCHLEVEL 5 + + #endif /* _PATCHLEVEL_H_ */ +diff --git a/subst.c b/subst.c +--- a/subst.c ++++ b/subst.c +@@ -8965,7 +8965,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/bash-5.2-patch-6.patch b/bash-5.2-patch-6.patch new file mode 100644 index 0000000..bcf4241 --- /dev/null +++ b/bash-5.2-patch-6.patch @@ -0,0 +1,230 @@ +diff --git a/builtins/common.h b/builtins/common.h +--- a/builtins/common.h ++++ b/builtins/common.h +@@ -257,6 +257,8 @@ extern int print_shift_error; + extern int expand_once_flag; + #endif + ++extern int expaliases_flag; ++ + /* variables from source.def */ + extern int source_searches_cwd; + extern int source_uses_path; +diff --git a/builtins/shopt.def b/builtins/shopt.def +--- a/builtins/shopt.def ++++ b/builtins/shopt.def +@@ -149,6 +149,9 @@ static int shopt_set_complete_direxpand PARAMS((char *, int)); + static int set_assoc_expand 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; +@@ -198,7 +201,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 +@@ -350,7 +353,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; +@@ -631,6 +634,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 (READLINE) + static int + shopt_enable_hostname_completion (option_name, mode) +diff --git a/execute_cmd.c b/execute_cmd.c +--- a/execute_cmd.c ++++ b/execute_cmd.c +@@ -1536,7 +1536,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. */ +diff --git a/general.c b/general.c +--- 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/parse.y b/parse.y +--- a/parse.y ++++ b/parse.y +@@ -3306,6 +3306,8 @@ reset_parser () + if (parser_state & (PST_EXTPAT|PST_CMDSUBST)) + extended_glob = global_extglob; + #endif ++ if (parser_state & (PST_CMDSUBST|PST_STRING)) ++ expand_aliases = expaliases_flag; + + parser_state = 0; + here_doc_first_line = 0; +@@ -4388,6 +4390,7 @@ parse_string_to_command (string, flags) + if (flags & SX_COMPLETE) + parser_state |= PST_NOERROR; + ++ parser_state |= PST_STRING; + expand_aliases = 0; + + cmd = 0; +@@ -6401,7 +6404,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 +--- 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/patchlevel.h b/patchlevel.h +--- 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 5 ++#define PATCHLEVEL 6 + + #endif /* _PATCHLEVEL_H_ */ +diff --git a/shell.c b/shell.c +--- 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/y.tab.c b/y.tab.c +--- a/y.tab.c ++++ b/y.tab.c +@@ -5617,6 +5617,8 @@ reset_parser () + if (parser_state & (PST_EXTPAT|PST_CMDSUBST)) + extended_glob = global_extglob; + #endif ++ if (parser_state & (PST_CMDSUBST|PST_STRING)) ++ expand_aliases = expaliases_flag; + + parser_state = 0; + here_doc_first_line = 0; +@@ -6699,6 +6701,7 @@ parse_string_to_command (string, flags) + if (flags & SX_COMPLETE) + parser_state |= PST_NOERROR; + ++ parser_state |= PST_STRING; + expand_aliases = 0; + + cmd = 0; +@@ -8712,7 +8715,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/bash-5.2-patch-7.patch b/bash-5.2-patch-7.patch new file mode 100644 index 0000000..0473773 --- /dev/null +++ b/bash-5.2-patch-7.patch @@ -0,0 +1,206 @@ +diff --git a/builtins/evalstring.c b/builtins/evalstring.c +--- a/builtins/evalstring.c ++++ b/builtins/evalstring.c +@@ -431,6 +431,8 @@ parse_and_execute (string, from_file, flags) + + if (parse_command () == 0) + { ++ int local_expalias, local_alflag; ++ + if ((flags & SEVAL_PARSEONLY) || (interactive_shell == 0 && read_but_dont_execute)) + { + last_result = EXECUTION_SUCCESS; +@@ -507,6 +509,19 @@ parse_and_execute (string, from_file, flags) + } + #endif /* ONESHOT */ + ++ /* We play tricks in the parser and command_substitute() turning ++ expand_aliases on and off depending on which parsing pass and ++ whether or not we're in posix mode. This only matters for ++ parsing, and we let the higher layers deal with that. We just ++ want to ensure that expand_aliases is set to the appropriate ++ global value when we go to execute this command, so we save ++ and restore it around the execution (we don't restore it if ++ the global value of the flag (expaliases_flag) changes). */ ++ local_expalias = expand_aliases; ++ local_alflag = expaliases_flag; ++ if (subshell_environment & SUBSHELL_COMSUB) ++ expand_aliases = expaliases_flag; ++ + /* See if this is a candidate for $( word : (char *)NULL; + if (tword) + dispose_word_desc (tword); +diff --git a/y.tab.c b/y.tab.c +--- a/y.tab.c ++++ b/y.tab.c +@@ -5923,6 +5923,7 @@ tokword: + #define P_BACKQUOTE 0x0010 /* parsing a backquoted command substitution */ + #define P_ARRAYSUB 0x0020 /* parsing a [...] array subscript for assignment */ + #define P_DOLBRACE 0x0040 /* parsing a ${...} construct */ ++#define P_ARITH 0x0080 /* parsing a $(( )) arithmetic expansion */ + + /* Lexical state while parsing a grouping construct or $(...). */ + #define LEX_WASDOL 0x0001 +@@ -6221,6 +6222,9 @@ parse_matched_pair (qc, open, close, lenp, flags) + } + else if ((flags & (P_ARRAYSUB|P_DOLBRACE)) && (tflags & LEX_WASDOL) && (ch == '(' || ch == '{' || ch == '[')) /* ) } ] */ + goto parse_dollar_word; ++ else if ((flags & P_ARITH) && (tflags & LEX_WASDOL) && ch == '(') /*)*/ ++ /* $() inside $(( ))/$[ ] */ ++ goto parse_dollar_word; + #if defined (PROCESS_SUBSTITUTION) + /* XXX - technically this should only be recognized at the start of + a word */ +@@ -6251,7 +6255,7 @@ parse_dollar_word: + else if (ch == '{') /* } */ + nestret = parse_matched_pair (0, '{', '}', &nestlen, P_FIRSTCLOSE|P_DOLBRACE|rflags); + else if (ch == '[') /* ] */ +- nestret = parse_matched_pair (0, '[', ']', &nestlen, rflags); ++ nestret = parse_matched_pair (0, '[', ']', &nestlen, rflags|P_ARITH); + + CHECK_NESTRET_ERROR (); + APPEND_NESTRET (); +@@ -6390,7 +6394,7 @@ parse_comsub (qc, open, close, lenp, flags) + peekc = shell_getc (1); + shell_ungetc (peekc); + if (peekc == '(') /*)*/ +- return (parse_matched_pair (qc, open, close, lenp, 0)); ++ return (parse_matched_pair (qc, open, close, lenp, P_ARITH)); + } + + /*itrace("parse_comsub: qc = `%c' open = %c close = %c", qc, open, close);*/ +@@ -6811,7 +6815,7 @@ parse_arith_cmd (ep, adddq) + int ttoklen; + + exp_lineno = line_number; +- ttok = parse_matched_pair (0, '(', ')', &ttoklen, 0); ++ ttok = parse_matched_pair (0, '(', ')', &ttoklen, P_ARITH); + rval = 1; + if (ttok == &matched_pair_error) + return -1; +@@ -7326,7 +7330,7 @@ read_token_word (character) + pop_delimiter (dstack); + } + else +- ttok = parse_matched_pair (cd, '[', ']', &ttoklen, 0); ++ ttok = parse_matched_pair (cd, '[', ']', &ttoklen, P_ARITH); + if (ttok == &matched_pair_error) + return -1; /* Bail immediately. */ + RESIZE_MALLOCED_BUFFER (token, token_index, ttoklen + 3, diff --git a/bash-5.2-patch-8.patch b/bash-5.2-patch-8.patch new file mode 100644 index 0000000..350bde3 --- /dev/null +++ b/bash-5.2-patch-8.patch @@ -0,0 +1,34 @@ +diff --git a/patchlevel.h b/patchlevel.h +--- 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 7 ++#define PATCHLEVEL 8 + + #endif /* _PATCHLEVEL_H_ */ +diff --git a/subst.c b/subst.c +--- a/subst.c ++++ b/subst.c +@@ -3819,6 +3819,10 @@ pos_params (string, start, end, quoted, pflags) + #define EXP_CHAR(s) (s == '$' || s == '`' || s == CTLESC || s == '~') + #endif + ++/* We don't perform process substitution in arithmetic expressions, so don't ++ bother checking for it. */ ++#define ARITH_EXP_CHAR(s) (s == '$' || s == '`' || s == CTLESC || s == '~') ++ + /* If there are any characters in STRING that require full expansion, + then call FUNC to expand STRING; otherwise just perform quote + removal if necessary. This returns a new string. */ +@@ -4028,7 +4032,7 @@ expand_arith_string (string, quoted) + i = saw_quote = 0; + while (string[i]) + { +- if (EXP_CHAR (string[i])) ++ if (ARITH_EXP_CHAR (string[i])) + break; + else if (string[i] == '\'' || string[i] == '\\' || string[i] == '"') + saw_quote = string[i]; diff --git a/bash-5.2-patch-9.patch b/bash-5.2-patch-9.patch new file mode 100644 index 0000000..ab4931f --- /dev/null +++ b/bash-5.2-patch-9.patch @@ -0,0 +1,23 @@ +diff --git a/expr.c b/expr.c +--- a/expr.c ++++ b/expr.c +@@ -1168,6 +1168,8 @@ expr_streval (tok, e, lvalue) + /* [[[[[ */ + #if defined (ARRAY_VARS) + aflag = tflag; /* use a different variable for now */ ++ if (shell_compatibility_level > 51) ++ aflag |= AV_ATSTARKEYS; + v = (e == ']') ? array_variable_part (tok, tflag, (char **)0, (int *)0) : find_variable (tok); + #else + v = find_variable (tok); +diff --git a/patchlevel.h b/patchlevel.h +--- 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 8 ++#define PATCHLEVEL 9 + + #endif /* _PATCHLEVEL_H_ */ diff --git a/bash.spec b/bash.spec index e87569e..7cc4a1e 100644 --- a/bash.spec +++ b/bash.spec @@ -1,12 +1,12 @@ #% define beta_tag rc2 -%define patchlevel 2 +%define patchlevel 9 %define baseversion 5.2 %bcond_without tests Version: %{baseversion}.%{patchlevel} Name: bash Summary: The GNU Bourne Again shell -Release: 2%{?dist} +Release: 1%{?dist} License: GPLv3+ Url: https://www.gnu.org/software/bash Source0: https://ftp.gnu.org/gnu/bash/bash-%{baseversion}.tar.gz @@ -89,10 +89,6 @@ Patch127: bash-4.4-no-loadable-builtins.patch # This option is undocumented in upstream and is documented by this patch Patch128: bash-5.0-syslog-history.patch -# 2133097 - bash fails to handle nested expansions -# This patch should be removed with next rebase -Patch129: bash-5.2-nested-expansion.patch - BuildRequires: gcc BuildRequires: texinfo bison BuildRequires: ncurses-devel @@ -324,6 +320,10 @@ end %{_libdir}/pkgconfig/%{name}.pc %changelog +* Fri Nov 18 2022 Siteshwar Vashisht - 5.2.9-1 +- Update to bash-5.2 patchlevel 9 + Resolves: #2140722 + * Mon Oct 10 2022 Siteshwar Vashisht - 5.2.2-2 - Fix an issue with nested expansions Resolves: #2133097