diff options
author | Chet Ramey <chet.ramey@case.edu> | 2022-11-07 11:42:44 -0500 |
---|---|---|
committer | Chet Ramey <chet.ramey@case.edu> | 2022-11-07 11:42:44 -0500 |
commit | 6ddc9cf242078c02c626ec60ee139c586da49bad (patch) | |
tree | bd895e1664b370d8950f1734acac3f666c528168 | |
parent | 8c9524f9c4b0242bd2239043118984b781bb60ab (diff) | |
download | bash-6ddc9cf242078c02c626ec60ee139c586da49bad.tar.gz |
Bash-5.2 patch 7: fixes for alias expansion inside command substitution in POSIX mode
-rw-r--r-- | builtins/evalstring.c | 19 | ||||
-rw-r--r-- | command.h | 1 | ||||
-rw-r--r-- | parse.y | 12 | ||||
-rw-r--r-- | patchlevel.h | 2 | ||||
-rw-r--r-- | subst.c | 10 | ||||
-rw-r--r-- | y.tab.c | 12 |
6 files changed, 44 insertions, 12 deletions
diff --git a/builtins/evalstring.c b/builtins/evalstring.c index fd635299..264a836b 100644 --- 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 $( <file ). */ if (startup_state == 2 && (subshell_environment & SUBSHELL_COMSUB) && @@ -524,6 +539,10 @@ parse_and_execute (string, from_file, flags) dispose_fd_bitmap (bitmap); discard_unwind_frame ("pe_dispose"); + /* If the global value didn't change, we restore what we had. */ + if ((subshell_environment & SUBSHELL_COMSUB) && local_alflag == expaliases_flag) + expand_aliases = local_expalias; + if (flags & SEVAL_ONECMD) { reset_parser (); @@ -114,6 +114,7 @@ enum command_type { cm_for, cm_case, cm_while, cm_if, cm_simple, cm_select, #define PF_COMPLETE 0x10 /* same as W_COMPLETE, sets SX_COMPLETE */ #define PF_EXPANDRHS 0x20 /* same as W_EXPANDRHS */ #define PF_ALLINDS 0x40 /* array, act as if [@] was supplied */ +#define PF_BACKQUOTE 0x80 /* differentiate `` from $() for command_substitute */ /* Possible values for subshell_environment */ #define SUBSHELL_ASYNC 0x01 /* subshell caused by `command &' */ @@ -3612,6 +3612,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 @@ -3910,6 +3911,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 */ @@ -3940,7 +3944,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 (); @@ -4079,7 +4083,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);*/ @@ -4500,7 +4504,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; @@ -5015,7 +5019,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/patchlevel.h b/patchlevel.h index 39d4c330..b1897c50 100644 --- 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 6 +#define PATCHLEVEL 7 #endif /* _PATCHLEVEL_H_ */ @@ -7123,8 +7123,12 @@ command_substitute (string, quoted, flags) remove_quoted_escapes (string); /* We want to expand aliases on this pass if we are not in posix mode - for backwards compatibility. */ - if (expand_aliases) + for backwards compatibility. parse_and_execute() takes care of + setting expand_aliases back to the global value when executing the + parsed string. We only do this for $(...) command substitution, + since that is what parse_comsub handles; `` comsubs are processed + using parse.y:parse_matched_pair(). */ + if (expand_aliases && (flags & PF_BACKQUOTE) == 0) expand_aliases = posixly_correct == 0; startup_state = 2; /* see if we can avoid a fork */ @@ -11292,7 +11296,7 @@ add_string: else { de_backslash (temp); - tword = command_substitute (temp, quoted, 0); + tword = command_substitute (temp, quoted, PF_BACKQUOTE); temp1 = tword ? tword->word : (char *)NULL; if (tword) dispose_word_desc (tword); @@ -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, |