Re: Interesting bug

2022-02-13 Thread Chet Ramey

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

2022-02-13 Thread Chet Ramey

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

2022-02-13 Thread vzvzvz2
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

2022-02-13 Thread Chet Ramey

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

2022-02-13 Thread Alex fxmbsw7 Ratchev
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

2022-02-13 Thread Dale R. Worley
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

2022-02-13 Thread Robert Elz
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

2022-02-13 Thread Dennis Williamson
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

2022-02-13 Thread Robert Elz
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