Re: Interesting bug
On 2/12/22 5:20 PM, David Hobach wrote: Thanks a lot for the detailed explanations, much appreciated! So essentially it's no bug - just a rather uncommon choice of keywords. I still don't agree with that choice since it can be abused to somewhat hide code in pull requests to less experienced maintainers, but oh well... there's probably enough fun to be had with unicode et al already. And I guess the more modern tastes are relatively recent in the history of bash. You may not agree with the choice of `{' and `}' as reserved words instead of operators, but that choice is at least 45 years old from the time Bourne made it. He probably had his own backwards compatibility concerns: scripts that used `{' and `}' as `normal' unquoted arguments that would have been broken by making them operators. -- ``The lyf so short, the craft so long to lerne.'' - Chaucer ``Ars longa, vita brevis'' - Hippocrates Chet Ramey, UTech, CWRUc...@case.eduhttp://tiswww.cwru.edu/~chet/
Re: Interesting bug
On 2/12/22 1:24 PM, David Hobach wrote: I guess 99% of programmers would either expect "Finished" to be printed or some syntax error. Well, 99% of shell programmers will (hopefully ;-) ) put a blank between "{" and "echo" in the line foo="$(testCode)" || {echo "foo";} Yes, the interesting part is that depending on which space you accidentally forget, you'll either get the expected "Finished" or "bad code executed". foo="$(testCode)" || {echo "foo"; } # --> bad code foo="$(testCode)" || { echo "foo";} # --> Finished I guess it closes the function and {echo is interpreted as string or so, but that is probably not all (testCode is e.g. never executed). It's not executed because it's part of a function that's never called. -- ``The lyf so short, the craft so long to lerne.'' - Chaucer ``Ars longa, vita brevis'' - Hippocrates Chet Ramey, UTech, CWRUc...@case.eduhttp://tiswww.cwru.edu/~chet/
Sus behaviour when cmd string ends with single backslash
Configuration Information [Automatically generated, do not change]: Machine: x86_64 OS: linux-gnu Compiler: gcc Compilation CFLAGS: -g -O2 -fdebug-prefix-map=/build/bash-a6qmCk/bash-5.0=. -fstack-protector-strong -Wformat -Werror=format-security -Wall -Wno-parentheses -Wno-format-security uname output: Linux zoli-linux 5.13.0-28-generic #31~20.04.1-Ubuntu SMP Wed Jan 19 14:08:10 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux Machine Type: x86_64-pc-linux-gnu Bash Version: 5.0 Patch Level: 17 Release Status: release Description: Background -- Commit a0c0a00fc419b7bc08202a79134fcd5bc0427071 (bash-4.4) introduced a change in parse.y with following documentation in the change logs: parse.y - shell_getc: if bash is reading input from a string that ends with an unquoted backslash, add another backslash instead of a newline, since the backslash and newline will disappear in normal processing. Fixes bug with `bash -c 'eval \\; echo y' ' skipping the eval command and setting incorrect exit status, and `bash -ic 'eval \\; echo y' ' seeing EOF on empty line and exiting before the echo. Keep track of backslash state with last_was_backslash; set in char reading loop. Fixes bug reported by Eduardo A. Bustamante López The new code in parse.y /* Don't add a newline to a string that ends with a backslash if we're going to be removing quoted newlines, since that will eat the backslash. Add another backslash instead (will be removed by word expansion). */ if (bash_input.type == st_string && expanding_alias() == 0 && last_was_backslash && c == EOF && remove_quoted_newline) shell_input_line[shell_input_line_len] = '\\'; else shell_input_line[shell_input_line_len] = '\n'; shell_input_line[shell_input_line_len + 1] = '\0'; This specific change is also there in commit 0385211bb5cb01e0259c64ec2c5cc6337d4e215c on a development branch. Observed vs. expected behaviour --- The mentioned bug is indeed fixed by this change. However, in case of another edge case following new behaviour is observable: $ bash -c 'echo \' \ $ # backslash appears on output The behaviour before the change was following: $ bash -c 'echo \' $ # no output This behaviour is observable since 4.4 up to the most current released version (5.1). I am not sure what is the correct behaviour here. My best guess is, that the single backslash at the end of the string should not be printed, because (bash man page): Quote Removal After the preceding expansions, all unquoted occurrences of the characters \, ', and " that did not result from one of the above expansions are removed. This behaviour would be consistent with the very same command took from a script: $ hexdump -C echo-with-newline.sh 65 63 68 6f 20 5c 0a |echo \.| 0007 $ hexdump -C echo-without-newline.sh 65 63 68 6f 20 5c |echo \| 0006 $ bash echo-with-newline.sh $ bash echo-without-newline.sh $ # no output in both cases Repeat-By: See commands in the description.
Re: shopt -u compat* (re)sets BASH_COMPAT to 51
On 2/12/22 4:11 AM, Mihai Moldovan wrote: Configuration Information [Automatically generated, do not change]: Machine: x86_64 OS: linux-gnu Compiler: x86_64-pc-linux-gnu-gcc Compilation CFLAGS: -march=native -mtune=native -Wall -pipe -g3 -ggdb3 -gdwarf-4 -O2 -fno-omit-frame-pointer uname output: Linux apgunner 5.15.11 #1 SMP PREEMPT Thu Dec 23 09:06:30 CET 2021 x86_64 Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz GenuineIntel GNU/Linux Machine Type: x86_64-pc-linux-gnu Bash Version: 5.1 Patch Level: 16 Release Status: release Description: The only way to set a compat level of 50 is to use the BASH_COMPAT variable. However, unsetting any compatNN shopt value will (re)set BASH_COMPAT to 51 (with bash-5.1), which is not something users might expect. Technically, the result isn't wrong, since, i.e., shopt -u compat43 did what it was asked to - not setting the compat value to 43. It's counter-intuitive and the old value should be retained, though. H. So what you're proposing is that `shopt -u compat43' if compat43 is not set should not reset the compatibility level to the current version. OK. I think we could do this by interrogating $BASH_COMPAT after unsetting the appropriate compat_NN option. Or maybe leaving shell_compatibility_level alone if it's > 44 (the last compat_NN option) and <= DEFAULT_COMPATIBILITY_LEVEL (the current version) instead of unconditionally setting it to DEFAULT_COMPATIBILITY_LEVEL. But then you'd be required to unset BASH_COMPAT to get back to the current compatibility level, which is supported now but not required. Chet -- ``The lyf so short, the craft so long to lerne.'' - Chaucer ``Ars longa, vita brevis'' - Hippocrates Chet Ramey, UTech, CWRUc...@case.eduhttp://tiswww.cwru.edu/~chet/
Re: Sus behaviour when cmd string ends with single backslash
On Sun, Feb 13, 2022, 22:23 wrote: > Configuration Information [Automatically generated, do not change]: > Machine: x86_64 > OS: linux-gnu > Compiler: gcc > Compilation CFLAGS: -g -O2 > -fdebug-prefix-map=/build/bash-a6qmCk/bash-5.0=. -fstack-protector-strong > -Wformat -Werror=format-security -Wall -Wno-parentheses -Wno-format-security > uname output: Linux zoli-linux 5.13.0-28-generic #31~20.04.1-Ubuntu SMP > Wed Jan 19 14:08:10 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux > Machine Type: x86_64-pc-linux-gnu > > Bash Version: 5.0 > Patch Level: 17 > Release Status: release > > Description: > > Background > -- > > Commit a0c0a00fc419b7bc08202a79134fcd5bc0427071 (bash-4.4) introduced a > change in parse.y with following documentation in the change logs: > > parse.y > - shell_getc: if bash is reading input from a string that ends > with an > unquoted backslash, add another backslash instead of a newline, > since > the backslash and newline will disappear in normal processing. > Fixes > bug with `bash -c 'eval \\; echo y' ' skipping the eval command > and > setting incorrect exit status, and `bash -ic 'eval \\; echo y' ' > seeing EOF on empty line and exiting before the echo. Keep > track of > backslash state with last_was_backslash; set in char reading > loop. > Fixes bug reported by Eduardo A. Bustamante López < > dual...@gmail.com> > > The new code in parse.y > > /* Don't add a newline to a string that ends with a backslash if > we're > going to be removing quoted newlines, since that will eat the > backslash. Add another backslash instead (will be removed by > word expansion). */ > if (bash_input.type == st_string && expanding_alias() == 0 && > last_was_backslash && c == EOF && remove_quoted_newline) > shell_input_line[shell_input_line_len] = '\\'; > else > shell_input_line[shell_input_line_len] = '\n'; > shell_input_line[shell_input_line_len + 1] = '\0'; > > > This specific change is also there in commit > 0385211bb5cb01e0259c64ec2c5cc6337d4e215c on a development branch. > > Observed vs. expected behaviour > --- > > The mentioned bug is indeed fixed by this change. However, in case of > another edge case following new behaviour is observable: > > $ bash -c 'echo \' > \ > $ # backslash appears on output > bash -c recognized a backslash due to smarter input checking as arg instead of newline break The behaviour before the change was following: > > $ bash -c 'echo \' > > $ # no output > bash -c recognized \ \n eof do you know, $' foo \' bar \' ' to preseeve 's if u dont This behaviour is observable since 4.4 up to the most current released > version (5.1). > > I am not sure what is the correct behaviour here. My best guess is, that > the single backslash at the end of the string should not be printed, > because (bash man page): > > Quote Removal >After the preceding expansions, all unquoted occurrences of the > characters \, ', and " that did not result >from one of the above expansions are removed. > > This behaviour would be consistent with the very same command took from a > script: > > $ hexdump -C echo-with-newline.sh > 65 63 68 6f 20 5c 0a |echo \.| > 0007 > $ hexdump -C echo-without-newline.sh > 65 63 68 6f 20 5c |echo \| > 0006 > $ bash echo-with-newline.sh > > $ bash echo-without-newline.sh > > $ # no output in both cases > > Repeat-By: > See commands in the description. > > >
Re: Sus behaviour when cmd string ends with single backslash
vzvz...@gmail.com writes: > The mentioned bug is indeed fixed by this change. However, in case of > another edge case following new behaviour is observable: > > $ bash -c 'echo \' > \ > $ # backslash appears on output It's an interesting case, since the command that Bash is executing is e-c-h-o-space-backslash with no character at all after the backslash. The manual page says A non-quoted backslash (\) is the escape character. It preserves the literal value of the next character that follows, with the exception of . If a \ pair appears, and the backslash is not it- self quoted, the \ is treated as a line continuation (that is, it is removed from the input stream and effectively ignored). Which doesn't seem to consider this case at all. The two a-priori plausable behaviors are for the backslash to be taken literally (which is what happens) or for it to vanish as some sort of incomplete escape construct. So you could plausibly say that the behavior of a backslash before "end of file" isn't defined. Dale
Re: Sus behaviour when cmd string ends with single backslash
Date:Sun, 13 Feb 2022 21:38:19 -0500 From:"Dale R. Worley" Message-ID: <87o83a895w@hobgoblin.ariadne.com> | The two a-priori plausable behaviors are for the backslash to be taken | literally (which is what happens) or for it to vanish as some sort of | incomplete escape construct. In most places, an unquoted trailing backslash (ie: followed by nothing) produces unspecified results. If you want a \ then quote it ( \\ will do, as would '\', but not "\" for the obvious reason...). When used with echo, things get even more messed up, as in some versions of echo, \ is an escape as well, and even if the shell you are using leaves the trailing \ intact, there is no guarantee that echo will, so even echo \\ is not necessarily going to produce a \ on stdout (there is no portable way using echo). Just avoid this kind of thing (and use printf instead of echo). kre
Re: Sus behaviour when cmd string ends with single backslash
On Sun, Feb 13, 2022, 9:48 PM Robert Elz wrote: > Date:Sun, 13 Feb 2022 21:38:19 -0500 > From:"Dale R. Worley" > Message-ID: <87o83a895w@hobgoblin.ariadne.com> > > | The two a-priori plausable behaviors are for the backslash to be taken > | literally (which is what happens) or for it to vanish as some sort of > | incomplete escape construct. > > In most places, an unquoted trailing backslash (ie: followed by > nothing) produces unspecified results. If you want a \ then > quote it ( \\ will do, as would '\', but not "\" for the obvious > reason...). > > When used with echo, things get even more messed up, as in some > versions of echo, \ is an escape as well, and even if the shell > you are using leaves the trailing \ intact, there is no guarantee > that echo will, so even echo \\ is not necessarily going to produce > a \ on stdout (there is no portable way using echo). > > Just avoid this kind of thing (and use printf instead of echo). > > kre > It occurs to me that the -r option of read is related.
Re: Sus behaviour when cmd string ends with single backslash
Date:Sun, 13 Feb 2022 22:38:47 -0600 From:Dennis Williamson Message-ID: | It occurs to me that the -r option of read is related. It is - if a backslash is the final char of input (ie: no newline follows) when read is used without -r, what happens to that \ will be unspecified. (With -r the input should simply be preserved, including any \ chars.) kre