From 780d665cfd32f8f3b28731d5b51fed5eacd7f4d4 Mon Sep 17 00:00:00 2001 From: Chet Ramey Date: Wed, 9 Feb 2022 10:15:16 -0500 Subject: [PATCH] fix to multiple alias expansion problem in command substitutions --- CWRU/CWRU.chlog | 33 +++++++ POSIX | 111 ++++++++++++---------- doc/bashref.info | 231 +++++++++++++++++++++++---------------------- doc/bashref.texi | 9 +- doc/version.texi | 6 +- include/shmbutil.h | 8 +- lib/sh/shquote.c | 25 ++--- parse.y | 16 ++++ subst.c | 5 + tests/comsub5.sub | 4 +- 10 files changed, 266 insertions(+), 182 deletions(-) diff --git a/CWRU/CWRU.chlog b/CWRU/CWRU.chlog index 446c3df4d..ffa5f1f5d 100644 --- a/CWRU/CWRU.chlog +++ b/CWRU/CWRU.chlog @@ -3054,3 +3054,36 @@ execute_cmd.c builtins/common.h,builtins/evalstring.c - optimize_fork: renamed to optimize_connection_fork; changed callers + 1/31 + ---- +include/shmbutil.h + - COPY_CHAR_I,SCOPY_CHAR_I: add check for locale_utf8locale and + (c & 0x80) as in other macros + +lib/sh/shquote.c + - sh_backslash_quote_for_double_quotes: rewrote to use array indexing + and COPY_CHAR_I to make it easier to drop in future calls to + charvis() to make `unsafe' characters visible if FLAGS == 1 + + 2/1 + --- +parse.y + - parse_comsub: if we are currently expanding aliases, temporarily + turn off alias expansion if we are not in posix mode so we defer + alias expansion until command_substitute(). Fixes double-expansion + bug reported by Martijn Dekker and aligns with + https://www.austingroupbugs.net/view.php?id=1342 + - xparse_dolparen: turn off alias expansion entirely while running the + parser: either we do it in parse_comsub (posix mode) or in + command_substitute (default mode) + - parse_string_to_command: ditto + +subst.c + - command_substitute: if we are expanding aliases, temporarily turn + off alias expansion if we are in posix mode, since we already + performed it in parse_comsub() and are using the command string + reconstituted from the parse result + +doc/bashref.texi + - bash posix mode: add description of alias expansion and command + substitution parsing and execution diff --git a/POSIX b/POSIX index fb513e534..d9368a2ff 100644 --- a/POSIX +++ b/POSIX @@ -33,73 +33,80 @@ The following list is what's changed when 'POSIX mode' is in effect: 7. Reserved words appearing in a context where reserved words are recognized do not undergo alias expansion. - 8. The POSIX 'PS1' and 'PS2' expansions of '!' to the history number + 8. Alias expansion is performed when initially parsing a command + substitution. The default mode generally defers it, when enabled, + until the command substitution is executed. This means that + command substitution will not expand aliases that are defined after + the command substitution is initially parsed (e.g., as part of a + function definition). + + 9. The POSIX 'PS1' and 'PS2' expansions of '!' to the history number and '!!' to '!' are enabled, and parameter expansion is performed on the values of 'PS1' and 'PS2' regardless of the setting of the 'promptvars' option. - 9. The POSIX startup files are executed ('$ENV') rather than the + 10. The POSIX startup files are executed ('$ENV') rather than the normal Bash files. - 10. Tilde expansion is only performed on assignments preceding a + 11. Tilde expansion is only performed on assignments preceding a command name, rather than on all assignment statements on the line. - 11. The default history file is '~/.sh_history' (this is the default + 12. The default history file is '~/.sh_history' (this is the default value of '$HISTFILE'). - 12. Redirection operators do not perform filename expansion on the + 13. Redirection operators do not perform filename expansion on the word in the redirection unless the shell is interactive. - 13. Redirection operators do not perform word splitting on the word in + 14. Redirection operators do not perform word splitting on the word in the redirection. - 14. Function names must be valid shell 'name's. That is, they may not + 15. Function names must be valid shell 'name's. That is, they may not contain characters other than letters, digits, and underscores, and may not start with a digit. Declaring a function with an invalid name causes a fatal syntax error in non-interactive shells. - 15. Function names may not be the same as one of the POSIX special + 16. Function names may not be the same as one of the POSIX special builtins. - 16. POSIX special builtins are found before shell functions during + 17. POSIX special builtins are found before shell functions during command lookup. - 17. When printing shell function definitions (e.g., by 'type'), Bash + 18. When printing shell function definitions (e.g., by 'type'), Bash does not print the 'function' keyword. - 18. Literal tildes that appear as the first character in elements of + 19. Literal tildes that appear as the first character in elements of the 'PATH' variable are not expanded as described above under *note Tilde Expansion::. - 19. The 'time' reserved word may be used by itself as a command. When + 20. The 'time' reserved word may be used by itself as a command. When used in this way, it displays timing statistics for the shell and its completed children. The 'TIMEFORMAT' variable controls the format of the timing information. - 20. When parsing and expanding a ${...} expansion that appears within + 21. When parsing and expanding a ${...} expansion that appears within double quotes, single quotes are no longer special and cannot be used to quote a closing brace or other special character, unless the operator is one of those defined to perform pattern removal. In this case, they do not have to appear as matched pairs. - 21. The parser does not recognize 'time' as a reserved word if the + 22. The parser does not recognize 'time' as a reserved word if the next token begins with a '-'. - 22. The '!' character does not introduce history expansion within a + 23. The '!' character does not introduce history expansion within a double-quoted string, even if the 'histexpand' option is enabled. - 23. If a POSIX special builtin returns an error status, a + 24. If a POSIX special builtin returns an error status, a non-interactive shell exits. The fatal errors are those listed in the POSIX standard, and include things like passing incorrect options, redirection errors, variable assignment errors for assignments preceding the command name, and so on. - 24. A non-interactive shell exits with an error status if a variable + 25. A non-interactive shell exits with an error status if a variable assignment error occurs when no command name follows the assignment statements. A variable assignment error occurs, for example, when trying to assign a value to a readonly variable. - 25. A non-interactive shell exits with an error status if a variable + 26. A non-interactive shell exits with an error status if a variable assignment error occurs in an assignment statement preceding a special builtin, but not with any other simple command. For any other simple command, the shell aborts execution of that command, @@ -107,133 +114,133 @@ The following list is what's changed when 'POSIX mode' is in effect: perform any further processing of the command in which the error occurred"). - 26. A non-interactive shell exits with an error status if the + 27. A non-interactive shell exits with an error status if the iteration variable in a 'for' statement or the selection variable in a 'select' statement is a readonly variable. - 27. Non-interactive shells exit if FILENAME in '.' FILENAME is not + 28. Non-interactive shells exit if FILENAME in '.' FILENAME is not found. - 28. Non-interactive shells exit if a syntax error in an arithmetic + 29. Non-interactive shells exit if a syntax error in an arithmetic expansion results in an invalid expression. - 29. Non-interactive shells exit if a parameter expansion error occurs. + 30. Non-interactive shells exit if a parameter expansion error occurs. - 30. Non-interactive shells exit if there is a syntax error in a script + 31. Non-interactive shells exit if there is a syntax error in a script read with the '.' or 'source' builtins, or in a string processed by the 'eval' builtin. - 31. While variable indirection is available, it may not be applied to + 32. While variable indirection is available, it may not be applied to the '#' and '?' special parameters. - 32. When expanding the '*' special parameter in a pattern context + 33. When expanding the '*' special parameter in a pattern context where the expansion is double-quoted does not treat the '$*' as if it were double-quoted. - 33. Assignment statements preceding POSIX special builtins persist in + 34. Assignment statements preceding POSIX special builtins persist in the shell environment after the builtin completes. - 34. The 'command' builtin does not prevent builtins that take + 35. The 'command' builtin does not prevent builtins that take assignment statements as arguments from expanding them as assignment statements; when not in POSIX mode, assignment builtins lose their assignment statement expansion properties when preceded by 'command'. - 35. The 'bg' builtin uses the required format to describe each job + 36. The 'bg' builtin uses the required format to describe each job placed in the background, which does not include an indication of whether the job is the current or previous job. - 36. The output of 'kill -l' prints all the signal names on a single + 37. The output of 'kill -l' prints all the signal names on a single line, separated by spaces, without the 'SIG' prefix. - 37. The 'kill' builtin does not accept signal names with a 'SIG' + 38. The 'kill' builtin does not accept signal names with a 'SIG' prefix. - 38. The 'export' and 'readonly' builtin commands display their output + 39. The 'export' and 'readonly' builtin commands display their output in the format required by POSIX. - 39. The 'trap' builtin displays signal names without the leading + 40. The 'trap' builtin displays signal names without the leading 'SIG'. - 40. The 'trap' builtin doesn't check the first argument for a possible + 41. The 'trap' builtin doesn't check the first argument for a possible signal specification and revert the signal handling to the original disposition if it is, unless that argument consists solely of digits and is a valid signal number. If users want to reset the handler for a given signal to the original disposition, they should use '-' as the first argument. - 41. 'trap -p' displays signals whose dispositions are set to SIG_DFL + 42. 'trap -p' displays signals whose dispositions are set to SIG_DFL and those that were ignored when the shell started. - 42. The '.' and 'source' builtins do not search the current directory + 43. The '.' and 'source' builtins do not search the current directory for the filename argument if it is not found by searching 'PATH'. - 43. Enabling POSIX mode has the effect of setting the + 44. Enabling POSIX mode has the effect of setting the 'inherit_errexit' option, so subshells spawned to execute command substitutions inherit the value of the '-e' option from the parent shell. When the 'inherit_errexit' option is not enabled, Bash clears the '-e' option in such subshells. - 44. Enabling POSIX mode has the effect of setting the 'shift_verbose' + 45. Enabling POSIX mode has the effect of setting the 'shift_verbose' option, so numeric arguments to 'shift' that exceed the number of positional parameters will result in an error message. - 45. When the 'alias' builtin displays alias definitions, it does not + 46. When the 'alias' builtin displays alias definitions, it does not display them with a leading 'alias ' unless the '-p' option is supplied. - 46. When the 'set' builtin is invoked without options, it does not + 47. When the 'set' builtin is invoked without options, it does not display shell function names and definitions. - 47. When the 'set' builtin is invoked without options, it displays + 48. When the 'set' builtin is invoked without options, it displays variable values without quotes, unless they contain shell metacharacters, even if the result contains nonprinting characters. - 48. When the 'cd' builtin is invoked in logical mode, and the pathname + 49. When the 'cd' builtin is invoked in logical mode, and the pathname constructed from '$PWD' and the directory name supplied as an argument does not refer to an existing directory, 'cd' will fail instead of falling back to physical mode. - 49. When the 'cd' builtin cannot change a directory because the length + 50. When the 'cd' builtin cannot change a directory because the length of the pathname constructed from '$PWD' and the directory name supplied as an argument exceeds 'PATH_MAX' when all symbolic links are expanded, 'cd' will fail instead of attempting to use only the supplied directory name. - 50. The 'pwd' builtin verifies that the value it prints is the same as + 51. The 'pwd' builtin verifies that the value it prints is the same as the current directory, even if it is not asked to check the file system with the '-P' option. - 51. When listing the history, the 'fc' builtin does not include an + 52. When listing the history, the 'fc' builtin does not include an indication of whether or not a history entry has been modified. - 52. The default editor used by 'fc' is 'ed'. + 53. The default editor used by 'fc' is 'ed'. - 53. The 'type' and 'command' builtins will not report a non-executable + 54. The 'type' and 'command' builtins will not report a non-executable file as having been found, though the shell will attempt to execute such a file if it is the only so-named file found in '$PATH'. - 54. The 'vi' editing mode will invoke the 'vi' editor directly when + 55. The 'vi' editing mode will invoke the 'vi' editor directly when the 'v' command is run, instead of checking '$VISUAL' and '$EDITOR'. - 55. When the 'xpg_echo' option is enabled, Bash does not attempt to + 56. When the 'xpg_echo' option is enabled, Bash does not attempt to interpret any arguments to 'echo' as options. Each argument is displayed, after escape characters are converted. - 56. The 'ulimit' builtin uses a block size of 512 bytes for the '-c' + 57. The 'ulimit' builtin uses a block size of 512 bytes for the '-c' and '-f' options. - 57. The arrival of 'SIGCHLD' when a trap is set on 'SIGCHLD' does not + 58. The arrival of 'SIGCHLD' when a trap is set on 'SIGCHLD' does not interrupt the 'wait' builtin and cause it to return immediately. The trap command is run once for each child that exits. - 58. The 'read' builtin may be interrupted by a signal for which a trap + 59. The 'read' builtin may be interrupted by a signal for which a trap has been set. If Bash receives a trapped signal while executing 'read', the trap handler executes and 'read' returns an exit status greater than 128. - 59. Bash removes an exited background process's status from the list + 60. Bash removes an exited background process's status from the list of such statuses after the 'wait' builtin is used to obtain it. There is other POSIX behavior that Bash does not implement by default diff --git a/doc/bashref.info b/doc/bashref.info index 8c8986c85..b9a966331 100644 --- a/doc/bashref.info +++ b/doc/bashref.info @@ -2,12 +2,12 @@ This is bashref.info, produced by makeinfo version 6.8 from bashref.texi. This text is a brief description of the features that are present in the -Bash shell (version 5.2, 17 January 2022). +Bash shell (version 5.2, 1 February 2022). - This is Edition 5.2, last updated 17 January 2022, of 'The GNU Bash + This is Edition 5.2, last updated 1 February 2022, of 'The GNU Bash Reference Manual', for 'Bash', Version 5.2. - Copyright (C) 1988-2021 Free Software Foundation, Inc. + Copyright (C) 1988-2022 Free Software Foundation, Inc. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, @@ -27,10 +27,10 @@ Bash Features ************* This text is a brief description of the features that are present in the -Bash shell (version 5.2, 17 January 2022). The Bash home page is +Bash shell (version 5.2, 1 February 2022). The Bash home page is . - This is Edition 5.2, last updated 17 January 2022, of 'The GNU Bash + This is Edition 5.2, last updated 1 February 2022, of 'The GNU Bash Reference Manual', for 'Bash', Version 5.2. Bash contains features that appear in other popular shells, and some @@ -7029,73 +7029,80 @@ startup files. 7. Reserved words appearing in a context where reserved words are recognized do not undergo alias expansion. - 8. The POSIX 'PS1' and 'PS2' expansions of '!' to the history number + 8. Alias expansion is performed when initially parsing a command + substitution. The default mode generally defers it, when enabled, + until the command substitution is executed. This means that + command substitution will not expand aliases that are defined after + the command substitution is initially parsed (e.g., as part of a + function definition). + + 9. The POSIX 'PS1' and 'PS2' expansions of '!' to the history number and '!!' to '!' are enabled, and parameter expansion is performed on the values of 'PS1' and 'PS2' regardless of the setting of the 'promptvars' option. - 9. The POSIX startup files are executed ('$ENV') rather than the + 10. The POSIX startup files are executed ('$ENV') rather than the normal Bash files. - 10. Tilde expansion is only performed on assignments preceding a + 11. Tilde expansion is only performed on assignments preceding a command name, rather than on all assignment statements on the line. - 11. The default history file is '~/.sh_history' (this is the default + 12. The default history file is '~/.sh_history' (this is the default value of '$HISTFILE'). - 12. Redirection operators do not perform filename expansion on the + 13. Redirection operators do not perform filename expansion on the word in the redirection unless the shell is interactive. - 13. Redirection operators do not perform word splitting on the word in + 14. Redirection operators do not perform word splitting on the word in the redirection. - 14. Function names must be valid shell 'name's. That is, they may not + 15. Function names must be valid shell 'name's. That is, they may not contain characters other than letters, digits, and underscores, and may not start with a digit. Declaring a function with an invalid name causes a fatal syntax error in non-interactive shells. - 15. Function names may not be the same as one of the POSIX special + 16. Function names may not be the same as one of the POSIX special builtins. - 16. POSIX special builtins are found before shell functions during + 17. POSIX special builtins are found before shell functions during command lookup. - 17. When printing shell function definitions (e.g., by 'type'), Bash + 18. When printing shell function definitions (e.g., by 'type'), Bash does not print the 'function' keyword. - 18. Literal tildes that appear as the first character in elements of + 19. Literal tildes that appear as the first character in elements of the 'PATH' variable are not expanded as described above under *note Tilde Expansion::. - 19. The 'time' reserved word may be used by itself as a command. When + 20. The 'time' reserved word may be used by itself as a command. When used in this way, it displays timing statistics for the shell and its completed children. The 'TIMEFORMAT' variable controls the format of the timing information. - 20. When parsing and expanding a ${...} expansion that appears within + 21. When parsing and expanding a ${...} expansion that appears within double quotes, single quotes are no longer special and cannot be used to quote a closing brace or other special character, unless the operator is one of those defined to perform pattern removal. In this case, they do not have to appear as matched pairs. - 21. The parser does not recognize 'time' as a reserved word if the + 22. The parser does not recognize 'time' as a reserved word if the next token begins with a '-'. - 22. The '!' character does not introduce history expansion within a + 23. The '!' character does not introduce history expansion within a double-quoted string, even if the 'histexpand' option is enabled. - 23. If a POSIX special builtin returns an error status, a + 24. If a POSIX special builtin returns an error status, a non-interactive shell exits. The fatal errors are those listed in the POSIX standard, and include things like passing incorrect options, redirection errors, variable assignment errors for assignments preceding the command name, and so on. - 24. A non-interactive shell exits with an error status if a variable + 25. A non-interactive shell exits with an error status if a variable assignment error occurs when no command name follows the assignment statements. A variable assignment error occurs, for example, when trying to assign a value to a readonly variable. - 25. A non-interactive shell exits with an error status if a variable + 26. A non-interactive shell exits with an error status if a variable assignment error occurs in an assignment statement preceding a special builtin, but not with any other simple command. For any other simple command, the shell aborts execution of that command, @@ -7103,133 +7110,133 @@ startup files. perform any further processing of the command in which the error occurred"). - 26. A non-interactive shell exits with an error status if the + 27. A non-interactive shell exits with an error status if the iteration variable in a 'for' statement or the selection variable in a 'select' statement is a readonly variable. - 27. Non-interactive shells exit if FILENAME in '.' FILENAME is not + 28. Non-interactive shells exit if FILENAME in '.' FILENAME is not found. - 28. Non-interactive shells exit if a syntax error in an arithmetic + 29. Non-interactive shells exit if a syntax error in an arithmetic expansion results in an invalid expression. - 29. Non-interactive shells exit if a parameter expansion error occurs. + 30. Non-interactive shells exit if a parameter expansion error occurs. - 30. Non-interactive shells exit if there is a syntax error in a script + 31. Non-interactive shells exit if there is a syntax error in a script read with the '.' or 'source' builtins, or in a string processed by the 'eval' builtin. - 31. While variable indirection is available, it may not be applied to + 32. While variable indirection is available, it may not be applied to the '#' and '?' special parameters. - 32. When expanding the '*' special parameter in a pattern context + 33. When expanding the '*' special parameter in a pattern context where the expansion is double-quoted does not treat the '$*' as if it were double-quoted. - 33. Assignment statements preceding POSIX special builtins persist in + 34. Assignment statements preceding POSIX special builtins persist in the shell environment after the builtin completes. - 34. The 'command' builtin does not prevent builtins that take + 35. The 'command' builtin does not prevent builtins that take assignment statements as arguments from expanding them as assignment statements; when not in POSIX mode, assignment builtins lose their assignment statement expansion properties when preceded by 'command'. - 35. The 'bg' builtin uses the required format to describe each job + 36. The 'bg' builtin uses the required format to describe each job placed in the background, which does not include an indication of whether the job is the current or previous job. - 36. The output of 'kill -l' prints all the signal names on a single + 37. The output of 'kill -l' prints all the signal names on a single line, separated by spaces, without the 'SIG' prefix. - 37. The 'kill' builtin does not accept signal names with a 'SIG' + 38. The 'kill' builtin does not accept signal names with a 'SIG' prefix. - 38. The 'export' and 'readonly' builtin commands display their output + 39. The 'export' and 'readonly' builtin commands display their output in the format required by POSIX. - 39. The 'trap' builtin displays signal names without the leading + 40. The 'trap' builtin displays signal names without the leading 'SIG'. - 40. The 'trap' builtin doesn't check the first argument for a possible + 41. The 'trap' builtin doesn't check the first argument for a possible signal specification and revert the signal handling to the original disposition if it is, unless that argument consists solely of digits and is a valid signal number. If users want to reset the handler for a given signal to the original disposition, they should use '-' as the first argument. - 41. 'trap -p' displays signals whose dispositions are set to SIG_DFL + 42. 'trap -p' displays signals whose dispositions are set to SIG_DFL and those that were ignored when the shell started. - 42. The '.' and 'source' builtins do not search the current directory + 43. The '.' and 'source' builtins do not search the current directory for the filename argument if it is not found by searching 'PATH'. - 43. Enabling POSIX mode has the effect of setting the + 44. Enabling POSIX mode has the effect of setting the 'inherit_errexit' option, so subshells spawned to execute command substitutions inherit the value of the '-e' option from the parent shell. When the 'inherit_errexit' option is not enabled, Bash clears the '-e' option in such subshells. - 44. Enabling POSIX mode has the effect of setting the 'shift_verbose' + 45. Enabling POSIX mode has the effect of setting the 'shift_verbose' option, so numeric arguments to 'shift' that exceed the number of positional parameters will result in an error message. - 45. When the 'alias' builtin displays alias definitions, it does not + 46. When the 'alias' builtin displays alias definitions, it does not display them with a leading 'alias ' unless the '-p' option is supplied. - 46. When the 'set' builtin is invoked without options, it does not + 47. When the 'set' builtin is invoked without options, it does not display shell function names and definitions. - 47. When the 'set' builtin is invoked without options, it displays + 48. When the 'set' builtin is invoked without options, it displays variable values without quotes, unless they contain shell metacharacters, even if the result contains nonprinting characters. - 48. When the 'cd' builtin is invoked in logical mode, and the pathname + 49. When the 'cd' builtin is invoked in logical mode, and the pathname constructed from '$PWD' and the directory name supplied as an argument does not refer to an existing directory, 'cd' will fail instead of falling back to physical mode. - 49. When the 'cd' builtin cannot change a directory because the length + 50. When the 'cd' builtin cannot change a directory because the length of the pathname constructed from '$PWD' and the directory name supplied as an argument exceeds 'PATH_MAX' when all symbolic links are expanded, 'cd' will fail instead of attempting to use only the supplied directory name. - 50. The 'pwd' builtin verifies that the value it prints is the same as + 51. The 'pwd' builtin verifies that the value it prints is the same as the current directory, even if it is not asked to check the file system with the '-P' option. - 51. When listing the history, the 'fc' builtin does not include an + 52. When listing the history, the 'fc' builtin does not include an indication of whether or not a history entry has been modified. - 52. The default editor used by 'fc' is 'ed'. + 53. The default editor used by 'fc' is 'ed'. - 53. The 'type' and 'command' builtins will not report a non-executable + 54. The 'type' and 'command' builtins will not report a non-executable file as having been found, though the shell will attempt to execute such a file if it is the only so-named file found in '$PATH'. - 54. The 'vi' editing mode will invoke the 'vi' editor directly when + 55. The 'vi' editing mode will invoke the 'vi' editor directly when the 'v' command is run, instead of checking '$VISUAL' and '$EDITOR'. - 55. When the 'xpg_echo' option is enabled, Bash does not attempt to + 56. When the 'xpg_echo' option is enabled, Bash does not attempt to interpret any arguments to 'echo' as options. Each argument is displayed, after escape characters are converted. - 56. The 'ulimit' builtin uses a block size of 512 bytes for the '-c' + 57. The 'ulimit' builtin uses a block size of 512 bytes for the '-c' and '-f' options. - 57. The arrival of 'SIGCHLD' when a trap is set on 'SIGCHLD' does not + 58. The arrival of 'SIGCHLD' when a trap is set on 'SIGCHLD' does not interrupt the 'wait' builtin and cause it to return immediately. The trap command is run once for each child that exits. - 58. The 'read' builtin may be interrupted by a signal for which a trap + 59. The 'read' builtin may be interrupted by a signal for which a trap has been set. If Bash receives a trapped signal while executing 'read', the trap handler executes and 'read' returns an exit status greater than 128. - 59. Bash removes an exited background process's status from the list + 60. Bash removes an exited background process's status from the list of such statuses after the 'wait' builtin is used to obtain it. There is other POSIX behavior that Bash does not implement by default @@ -12520,61 +12527,61 @@ Node: Directory Stack Builtins288792 Node: Controlling the Prompt293052 Node: The Restricted Shell296017 Node: Bash POSIX Mode298627 -Node: Shell Compatibility Mode309900 -Node: Job Control317929 -Node: Job Control Basics318389 -Node: Job Control Builtins323391 -Node: Job Control Variables328791 -Node: Command Line Editing329947 -Node: Introduction and Notation331618 -Node: Readline Interaction333241 -Node: Readline Bare Essentials334432 -Node: Readline Movement Commands336215 -Node: Readline Killing Commands337175 -Node: Readline Arguments339093 -Node: Searching340137 -Node: Readline Init File342323 -Node: Readline Init File Syntax343584 -Node: Conditional Init Constructs365072 -Node: Sample Init File369268 -Node: Bindable Readline Commands372392 -Node: Commands For Moving373596 -Node: Commands For History375647 -Node: Commands For Text380641 -Node: Commands For Killing384290 -Node: Numeric Arguments387323 -Node: Commands For Completion388462 -Node: Keyboard Macros392653 -Node: Miscellaneous Commands393340 -Node: Readline vi Mode399279 -Node: Programmable Completion400186 -Node: Programmable Completion Builtins407966 -Node: A Programmable Completion Example418661 -Node: Using History Interactively423908 -Node: Bash History Facilities424592 -Node: Bash History Builtins427597 -Node: History Interaction432605 -Node: Event Designators436225 -Node: Word Designators437579 -Node: Modifiers439339 -Node: Installing Bash441150 -Node: Basic Installation442287 -Node: Compilers and Options446009 -Node: Compiling For Multiple Architectures446750 -Node: Installation Names448443 -Node: Specifying the System Type450552 -Node: Sharing Defaults451268 -Node: Operation Controls451941 -Node: Optional Features452899 -Node: Reporting Bugs464117 -Node: Major Differences From The Bourne Shell465392 -Node: GNU Free Documentation License482242 -Node: Indexes507419 -Node: Builtin Index507873 -Node: Reserved Word Index514700 -Node: Variable Index517148 -Node: Function Index533640 -Node: Concept Index547424 +Node: Shell Compatibility Mode310277 +Node: Job Control318306 +Node: Job Control Basics318766 +Node: Job Control Builtins323768 +Node: Job Control Variables329168 +Node: Command Line Editing330324 +Node: Introduction and Notation331995 +Node: Readline Interaction333618 +Node: Readline Bare Essentials334809 +Node: Readline Movement Commands336592 +Node: Readline Killing Commands337552 +Node: Readline Arguments339470 +Node: Searching340514 +Node: Readline Init File342700 +Node: Readline Init File Syntax343961 +Node: Conditional Init Constructs365449 +Node: Sample Init File369645 +Node: Bindable Readline Commands372769 +Node: Commands For Moving373973 +Node: Commands For History376024 +Node: Commands For Text381018 +Node: Commands For Killing384667 +Node: Numeric Arguments387700 +Node: Commands For Completion388839 +Node: Keyboard Macros393030 +Node: Miscellaneous Commands393717 +Node: Readline vi Mode399656 +Node: Programmable Completion400563 +Node: Programmable Completion Builtins408343 +Node: A Programmable Completion Example419038 +Node: Using History Interactively424285 +Node: Bash History Facilities424969 +Node: Bash History Builtins427974 +Node: History Interaction432982 +Node: Event Designators436602 +Node: Word Designators437956 +Node: Modifiers439716 +Node: Installing Bash441527 +Node: Basic Installation442664 +Node: Compilers and Options446386 +Node: Compiling For Multiple Architectures447127 +Node: Installation Names448820 +Node: Specifying the System Type450929 +Node: Sharing Defaults451645 +Node: Operation Controls452318 +Node: Optional Features453276 +Node: Reporting Bugs464494 +Node: Major Differences From The Bourne Shell465769 +Node: GNU Free Documentation License482619 +Node: Indexes507796 +Node: Builtin Index508250 +Node: Reserved Word Index515077 +Node: Variable Index517525 +Node: Function Index534017 +Node: Concept Index547801  End Tag Table diff --git a/doc/bashref.texi b/doc/bashref.texi index 061095259..7ebedac22 100644 --- a/doc/bashref.texi +++ b/doc/bashref.texi @@ -14,7 +14,7 @@ This is Edition @value{EDITION}, last updated @value{UPDATED}, of @cite{The GNU Bash Reference Manual}, for @code{Bash}, Version @value{VERSION}. -Copyright @copyright{} 1988--2021 Free Software Foundation, Inc. +Copyright @copyright{} 1988--2022 Free Software Foundation, Inc. @quotation Permission is granted to copy, distribute and/or modify this document @@ -8115,6 +8115,13 @@ Alias expansion is always enabled, even in non-interactive shells. Reserved words appearing in a context where reserved words are recognized do not undergo alias expansion. +@item +Alias expansion is performed when initially parsing a command substitution. +The default mode generally defers it, when enabled, until the command +substitution is executed. This means that command substitution will not +expand aliases that are defined after the command substitution is initially +parsed (e.g., as part of a function definition). + @item The @sc{posix} @env{PS1} and @env{PS2} expansions of @samp{!} to the history number and @samp{!!} to @samp{!} are enabled, diff --git a/doc/version.texi b/doc/version.texi index 5f05614bd..a8709b553 100644 --- a/doc/version.texi +++ b/doc/version.texi @@ -2,10 +2,10 @@ Copyright (C) 1988-2022 Free Software Foundation, Inc. @end ignore -@set LASTCHANGE Mon Jan 17 17:03:25 EST 2022 +@set LASTCHANGE Tue Feb 1 13:25:53 EST 2022 @set EDITION 5.2 @set VERSION 5.2 -@set UPDATED 17 January 2022 -@set UPDATED-MONTH January 2022 +@set UPDATED 1 February 2022 +@set UPDATED-MONTH February 2022 diff --git a/include/shmbutil.h b/include/shmbutil.h index 835fb80cd..5ef3a7c5c 100644 --- a/include/shmbutil.h +++ b/include/shmbutil.h @@ -318,9 +318,11 @@ extern int locale_utf8locale; /* XXX */ size_t mblength; \ int _k; \ \ - _k = is_basic (*((_src) + (_si))); \ + _k = is_basic ((_src)[(_si)]); \ if (_k) \ mblength = 1; \ + else if (locale_utf8locale && ((_src)[(_si)] & 0x80) == 0) \ + mblength = (_src)[(_si)] != 0; \ else \ {\ state_bak = state; \ @@ -361,9 +363,11 @@ extern int locale_utf8locale; /* XXX */ size_t mblength; \ int _i; \ \ - _i = is_basic (*((_src) + (_si))); \ + _i = is_basic ((_src)[(_si)]); \ if (_i) \ mblength = 1; \ + else if (locale_utf8locale && ((_src)[(_si)] & 0x80) == 0) \ + mblength = (_src)[(_si)] != 0; \ else \ { \ state_bak = state; \ diff --git a/lib/sh/shquote.c b/lib/sh/shquote.c index 9f5ca3def..c67be2533 100644 --- a/lib/sh/shquote.c +++ b/lib/sh/shquote.c @@ -313,46 +313,49 @@ sh_backslash_quote (string, table, flags) #if defined (PROMPT_STRING_DECODE) || defined (TRANSLATABLE_STRINGS) /* Quote characters that get special treatment when in double quotes in STRING - using backslashes. Return a new string. */ + using backslashes. If FLAGS == 1, also make `unsafe' characters visible by + translating them to a standard ^X/M-X representation (not yet implemented). + Return a new string. */ char * sh_backslash_quote_for_double_quotes (string, flags) char *string; int flags; { unsigned char c; - char *result, *r, *s, *send; - size_t slen; + char *result, *send; + size_t slen, sind, rind; int mb_cur_max; DECLARE_MBSTATE; slen = strlen (string); send = string + slen; mb_cur_max = MB_CUR_MAX; - result = (char *)xmalloc (2 * slen + 1); + result = (char *)xmalloc ((flags == 1 ? 3 : 2) * slen + 1); - for (r = result, s = string; s && (c = *s); s++) + for (rind = sind = 0; c = string[sind]; sind++) { /* Backslash-newline disappears within double quotes, so don't add one. */ + if ((sh_syntaxtab[c] & CBSDQUOTE) && c != '\n') - *r++ = '\\'; + result[rind++] = '\\'; /* I should probably use the CSPECL flag for these in sh_syntaxtab[] */ else if (c == CTLESC || c == CTLNUL) - *r++ = CTLESC; /* could be '\\'? */ + result[rind++] = CTLESC; /* could be '\\'? */ #if defined (HANDLE_MULTIBYTE) if ((locale_utf8locale && (c & 0x80)) || (locale_utf8locale == 0 && mb_cur_max > 1 && is_basic (c) == 0)) { - COPY_CHAR_P (r, s, send); - s--; /* compensate for auto-increment in loop above */ + COPY_CHAR_I (result, rind, string, send, sind); + sind--; /* compensate for auto-increment in loop above */ continue; } #endif - *r++ = c; + result[rind++] = c; } - *r = '\0'; + result[rind] = '\0'; return (result); } #endif /* PROMPT_STRING_DECODE */ diff --git a/parse.y b/parse.y index b97d2c88a..7e6a161ee 100644 --- a/parse.y +++ b/parse.y @@ -4071,6 +4071,13 @@ parse_comsub (qc, open, close, lenp, flags) need_here_doc = 0; esacs_needed_count = expecting_in_token = 0; + /* We want to expand aliases on this pass if we're in posix mode, since the + standard says you have to take aliases into account when looking for the + terminating right paren. Otherwise, we defer until execution time for + backwards compatibility. */ + if (expand_aliases) + expand_aliases = posixly_correct != 0; + current_token = '\n'; /* XXX */ token_to_read = DOLPAREN; /* let's trick the parser */ @@ -4175,6 +4182,13 @@ xparse_dolparen (base, string, indp, flags) if (flags & SX_COMPLETE) parser_state |= PST_NOERROR; + /* Don't expand aliases on this pass at all. Either parse_comsub() does it + at parse time, in which case this string already has aliases expanded, + or command_substitute() does it in the child process executing the + command substitution and we want to defer it completely until then. The + old value will be restored by restore_parser_state(). */ + expand_aliases = 0; + token_to_read = DOLPAREN; /* let's trick the parser */ nc = parse_string (string, "command substitution", sflags, (COMMAND **)NULL, &ep); @@ -4287,6 +4301,8 @@ parse_string_to_command (string, flags) if (flags & SX_COMPLETE) parser_state |= PST_NOERROR; + expand_aliases = 0; + cmd = 0; nc = parse_string (string, "command substitution", sflags, &cmd, &ep); diff --git a/subst.c b/subst.c index 33f5a2245..514a269a0 100644 --- a/subst.c +++ b/subst.c @@ -7112,6 +7112,11 @@ 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) + expand_aliases = posixly_correct == 0; + startup_state = 2; /* see if we can avoid a fork */ parse_and_execute_level = 0; diff --git a/tests/comsub5.sub b/tests/comsub5.sub index 1ec41645c..48bf62d4b 100644 --- a/tests/comsub5.sub +++ b/tests/comsub5.sub @@ -13,9 +13,11 @@ # # this is a new feature: expanding aliases when initially parsing command -# substitutions +# substitutions. required by posix, so enabled in posix mode. default mode +# stays backwards compatible. shopt -s expand_aliases +set -o posix alias switch=case -- 2.47.2