]> git.ipfire.org Git - thirdparty/bash.git/commitdiff
Bash-5.2 patch 7: fixes for alias expansion inside command substitution in POSIX...
authorChet Ramey <chet.ramey@case.edu>
Mon, 7 Nov 2022 16:42:44 +0000 (11:42 -0500)
committerChet Ramey <chet.ramey@case.edu>
Mon, 7 Nov 2022 16:42:44 +0000 (11:42 -0500)
builtins/evalstring.c
command.h
parse.y
patchlevel.h
subst.c
y.tab.c

index fd635299581f57369fe999365d998de6669f7edb..264a836b3af314216cba82df937c03649bf37c1b 100644 (file)
@@ -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 ();
index e0dc2f955764f7a15ea35505c32f76bf3cf72fa3..6230354ba1cc92b327555fc47664079d94cfa5c4 100644 (file)
--- a/command.h
+++ b/command.h
@@ -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 &' */
diff --git a/parse.y b/parse.y
index b00b3d686f94c6e126e797677b11df5ddcdd55cc..32f23961dee1ad705c52f282cf9863ff28075b81 100644 (file)
--- a/parse.y
+++ b/parse.y
@@ -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,
index 39d4c3307dbbd76b238c1d28609e5a9bec88efff..b1897c5033310f6cc0b64ea294566eac6ed2702f 100644 (file)
@@ -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_ */
diff --git a/subst.c b/subst.c
index b22fc64be2cb12448f902651fdd376b9b787ea8e..dcf2e46c2ea317cab1e81b74c080f88619f8f002 100644 (file)
--- a/subst.c
+++ b/subst.c
@@ -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);
diff --git a/y.tab.c b/y.tab.c
index 0e516e6dedf5f1ee783ef349f8cb449e3a44a824..71f9e0719cc07ed0d2a752ac58dc32a149791cdc 100644 (file)
--- 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,