BASH PATCH REPORT ================= Bash-Release: 5.2 Patch-ID: bash52-034 Bug-Reported-by: Wiley Young Bug-Reference-ID: Bug-Reference-URL: https://lists.gnu.org/archive/html/bug-bash/2023-05/msg00146.html Bug-Description: If we parse a compound assignment during an alias expansion, it's possible to have the current input string popped out from underneath the parse. In this case, we should not restore the input we were using when we began to parse the compound assignment. Patch (apply with `patch -p0'): *** ../bash-5.2-patched/parse.y Fri May 26 16:57:03 2023 --- parse.y Thu Jun 1 16:30:19 2023 *************** *** 6854,6860 **** { WORD_LIST *wl, *rl; ! int tok, orig_line_number, assignok; sh_parser_state_t ps; char *ret; orig_line_number = line_number; --- 6858,6865 ---- { WORD_LIST *wl, *rl; ! int tok, orig_line_number, assignok, ea, restore_pushed_strings; sh_parser_state_t ps; char *ret; + STRING_SAVER *ss; orig_line_number = line_number; *************** *** 6879,6882 **** --- 6884,6893 ---- esacs_needed_count = expecting_in_token = 0; + /* We're not pushing any new input here, we're reading from the current input + source. If that's an alias, we have to be prepared for the alias to get + popped out from underneath us. */ + ss = (ea = expanding_alias ()) ? pushed_string_list : (STRING_SAVER *)NULL; + restore_pushed_strings = 0; + while ((tok = read_token (READ)) != ')') { *************** *** 6902,6906 **** --- 6913,6926 ---- } + /* Check whether or not an alias got popped out from underneath us and + fix up after restore_parser_state. */ + if (ea && ss && ss != pushed_string_list) + { + restore_pushed_strings = 1; + ss = pushed_string_list; + } restore_parser_state (&ps); + if (restore_pushed_strings) + pushed_string_list = ss; if (wl == &parse_string_error) *** ../bash-5.2-patched/y.tab.c Mon Sep 23 10:02:46 2024 --- y.tab.c Mon Sep 23 10:02:49 2024 *************** *** 8804,8812 **** int *retlenp; { WORD_LIST *wl, *rl; ! int tok, orig_line_number, assignok; sh_parser_state_t ps; char *ret; orig_line_number = line_number; save_parser_state (&ps); --- 8804,8813 ---- int *retlenp; { WORD_LIST *wl, *rl; ! int tok, orig_line_number, assignok, ea, restore_pushed_strings; sh_parser_state_t ps; char *ret; + STRING_SAVER *ss; orig_line_number = line_number; save_parser_state (&ps); *************** *** 8829,8834 **** --- 8830,8841 ---- esacs_needed_count = expecting_in_token = 0; + /* We're not pushing any new input here, we're reading from the current input + source. If that's an alias, we have to be prepared for the alias to get + popped out from underneath us. */ + ss = (ea = expanding_alias ()) ? pushed_string_list : (STRING_SAVER *)NULL; + restore_pushed_strings = 0; + while ((tok = read_token (READ)) != ')') { if (tok == '\n') /* Allow newlines in compound assignments */ *************** *** 8852,8858 **** --- 8859,8874 ---- wl = make_word_list (yylval.word, wl); } + /* Check whether or not an alias got popped out from underneath us and + fix up after restore_parser_state. */ + if (ea && ss && ss != pushed_string_list) + { + restore_pushed_strings = 1; + ss = pushed_string_list; + } restore_parser_state (&ps); + if (restore_pushed_strings) + pushed_string_list = ss; if (wl == &parse_string_error) { *** ../bash-5.2/patchlevel.h 2020-06-22 14:51:03.000000000 -0400 --- patchlevel.h 2020-10-01 11:01:28.000000000 -0400 *************** *** 26,30 **** looks for to find the patch level (for the sccs version string). */ ! #define PATCHLEVEL 33 #endif /* _PATCHLEVEL_H_ */ --- 26,30 ---- looks for to find the patch level (for the sccs version string). */ ! #define PATCHLEVEL 34 #endif /* _PATCHLEVEL_H_ */