backslashes in output of command substitution trigger GLOB

2020-10-10 Thread idallen
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 idallen-oak 5.4.0-48-generic #52-Ubuntu SMP Thu Sep 10 
10:58:49 UTC 2020 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:
If a word in the output of a command substitution contains a
backslash, and the word (without backslash) happens to match a
file name, the shell will replace the word with the file name.
The backslashes will disappear.  If the word doesn't match a file
name, the backslashes are preserved.

Backslashes are not GLOB characters.  This matching should not happen.

Turn on "shopt -s failglob".  Now, if a word in the output of a
command substitution contains a backslash, and the word (without
the backslash) doesn't match a filename, bash gives a GLOB "no
match" error.  Backslashes are not GLOB characters.  This error
should not happen.

I noticed this bug because many of the bash completion scripts don't
work for me because I use "shopt -s failglob" in my .bashrc and many
of the completion scripts don't properly quote to protect against
GLOB expansion.  I saw a "no match" error for a word that didn't
have any GLOB characters in it, but did have a backslash.  Bug found.

Repeat-By:

# Run "bash --norc" and enter an empty directory and do these things below.
# The first section runs without failglob; the second section with.
# The unexpected output is flagged with "NOT EXPECTED" below.

bash-5.0$ shopt -u failglob
bash-5.0$ echo '\a' >/tmp/foo  # create a file with just \a in it
bash-5.0$ echo \a
a
bash-5.0$ echo $(echo '\a')
\a
bash-5.0$ echo $(cat /tmp/foo)
\a
bash-5.0$ touch a
bash-5.0$ echo $(echo '\a')
a<=== NOT EXPECTED!
bash-5.0$ echo $(cat /tmp/foo)
a<=== NOT EXPECTED!
bash-5.0$ echo $(echo '\a\b\c\d\e\f')
\a\b\c\d\e\f
bash-5.0$ touch abcdef
bash-5.0$ echo $(echo '\a\b\c\d\e\f')
abcdef   <=== NOT EXPECTED

bash-5.0$ shopt -s failglob
bash-5.0$ rm *
bash-5.0$ echo \a
a
bash-5.0$ echo $(echo '\a')
bash: no match: \a   <=== NOT EXPECTED!
bash-5.0$ echo $(cat /tmp/foo)
bash: no match: \a   <=== NOT EXPECTED!
bash-5.0$ touch a
bash-5.0$ echo $(echo '\a')
a<=== NOT EXPECTED!
bash-5.0$ echo $(cat /tmp/foo)
a<=== NOT EXPECTED!
bash-5.0$ echo $(echo '\a\b\c\d\e\f')
bash: no match: \a\b\c\d\e\f <=== NOT EXPECTED!
bash-5.0$ touch abcdef
bash-5.0$ echo $(echo '\a\b\c\d\e\f')
abcdef   <=== NOT EXPECTED




commands do not ignore TSTP if TSTP ignored already

2014-10-15 Thread idallen
Configuration Information [Automatically generated, do not change]:
Machine: x86_64
OS: linux-gnu
Compiler: gcc
Compilation CFLAGS:  -DPROGRAM='bash' -DCONF_HOSTTYPE='x86_64' 
-DCONF_OSTYPE='linux-gnu' -DCONF_MACHTYPE='x86_64-pc-linux-gnu' 
-DCONF_VENDOR='pc' -DLOCALEDIR='/usr/share/locale' -DPACKAGE='bash' -DSHELL 
-DHAVE_CONFIG_H   -I.  -I../bash -I../bash/include -I../bash/lib  
-D_FORTIFY_SOURCE=2 -g -O2 -fstack-protector --param=ssp-buffer-size=4 -Wformat 
-Wformat-security -Werror=format-security -Wall
uname output: Linux idallen-oak.home.idallen.ca 3.13.0-37-generic 
#64~precise1-Ubuntu SMP Wed Sep 24 21:37:11 UTC 2014 x86_64 x86_64 x86_64 
GNU/Linux
Machine Type: x86_64-pc-linux-gnu

Bash Version: 4.2
Patch Level: 25
Release Status: release

Description:

If a bash shell script starts up with TSTP ignored, commands run by that
script will not ignore TSTP, even if you set a trap in the script to
ignore TSTP.  If the script starts up with TSTP not ignored, then the
trap to ignore TSTP works fine.

Repeat-By:

Create these two scripts below one.sh and two.sh and run ./one.sh and use
^Z to signal TSTP.  The "sleep" will stop, even though TSTP is ignored.

Remove (comment out) the "trap" line from one.sh and run ./one.sh and
now ^Z (TSTP) is properly ignored when two.sh runs.

==> one.sh <==
#!/bin/bash
trap '' TSTP
exec ./two.sh

==> two.sh <==
#!/bin/bash
trap '' TSTP
while : ; do
echo "DEBUG"
sleep 1
done



unexpected tilde quoting change in version 4.3

2014-10-22 Thread idallen
Bash Version: 4.2 and 4.3

Description:

I find this change in quoting from 4.2 to 4.3 odd, where double-quoted
"~" used to be quoted (no expansion) and no longer works:

Bash version 4.2.25(1)-release:

$ x=foo
$ y="${x/foo/\~}"   # backslash is more than is needed
$ echo "$y"
\~
$ y="${x/foo/~}"# double quotes work
$ echo "$y"
~
$ y=${x/foo/\~} # backslash also works
$ echo "$y"
~
$ y=${x/foo/~}  # expands (okay)
$ echo "$y"   
/home/idallen

Bash 4.3 takes extra work to hide the tilde:

$ x=foo
$ y="${x/foo/\~}"# need both double quotes *and* backslash !?
$ echo "$y"
~
    $ y="${x/foo/~}" # doesn't quote any more (worked in 4.2)
$ echo "$y"
/home/idallen
$ y=${x/foo/\~}  # quotes same as 4.2
$ echo "$y"
~
$ y=${x/foo/~}   # expands same as 4.2
$ echo "$y"   
/home/idallen

Is this an intentional change?



set -o notify spurious CR when jobs redirected to file

2014-11-13 Thread idallen
Configuration Information [Automatically generated, do not change]:
Machine: x86_64
OS: linux-gnu
Compiler: gcc
Compilation CFLAGS:  -DPROGRAM='bash' -DCONF_HOSTTYPE='x86_64' 
-DCONF_OSTYPE='linux-gnu' -DCONF_MACHTYPE='x86_64-pc-linux-gnu' 
-DCONF_VENDOR='pc' -DLOCALEDIR='/usr/share/locale' -DPACKAGE='bash' -DSHELL 
-DHAVE_CONFIG_H   -I.  -I../bash -I../bash/include -I../bash/lib  
-D_FORTIFY_SOURCE=2 -g -O2 -fstack-protector --param=ssp-buffer-size=4 -Wformat 
-Wformat-security -Werror=format-security -Wall
uname output: Linux idallen-oak.home.idallen.ca 3.13.0-40-generic 
#68~precise1-Ubuntu SMP Tue Nov 4 16:00:24 UTC 2014 x86_64 x86_64 x86_64 
GNU/Linux
Machine Type: x86_64-pc-linux-gnu

Bash Version: 4.2
Patch Level: 25
Release Status: release

Description:
Using "set -o notify" adds spurious CR to output of "jobs"
when output is redirected to a file (but not into a pipe).

Repeat-By:

$ sleep 999 &
[1] 16386
$ set +o notify
$ jobs >out
$ file out
out: ASCII text
$ set -o notify
$ jobs >out
$ file out
out: ASCII text, with CRLF line terminators
$ od -c out
000   [   1   ]   +   R   u   n   n   i   n   g
020   s   l
040   e   e   p   9   9   9   &  \r  \n
053
$ jobs | od -c
000   [   1   ]   +   R   u   n   n   i   n   g
020   s   l
040   e   e   p   9   9   9   &  \n
052




filename TAB completion breaks using "force write" redirection syntax

2015-06-16 Thread idallen
Configuration Information [Automatically generated, do not change]:
Machine: x86_64
OS: linux-gnu
Compiler: gcc
Compilation CFLAGS:  -DPROGRAM='bash' -DCONF_HOSTTYPE='x86_64' 
-DCONF_OSTYPE='linux-gnu' -DCONF_MACHTYPE='x86_64-pc-linux-gnu' 
-DCONF_VENDOR='pc' -DLOCALEDIR='/usr/share/locale' -DPACKAGE='bash' -DSHELL 
-DHAVE_CONFIG_H   -I.  -I../. -I.././include -I.././lib  -D_FORTIFY_SOURCE=2 -g 
-O2 -fstack-protector-strong -Wformat -Werror=format-security -Wall
uname output: Linux idallen-oak 3.19.0-20-generic #20-Ubuntu SMP Fri May 29 
10:10:47 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux
Machine Type: x86_64-pc-linux-gnu

Bash Version: 4.3
Patch Level: 30
Release Status: release

Description:
I don't know if this bug applies to bash or to bash-completion.
Reference: "man bash" section "Redirecting Output"

Filename TAB completion breaks using "force write" redirection syntax.

The use of the "pipe" symbol after the ">" makes the completion think that 
a command name is required instead of a file name.

Repeat-By:
$ cd /tmp
$ touch foobar
$ set -o noclobber
$ date > foo
 foobar # this is expanded correctly to the file name
bash: foobar: cannot overwrite existing file # this is correct

$ date >| foo  # using overwrite syntax triggers command name expansion
foo2hbpl2   foo2lava-wrapperfoo2xqx
foo2hbpl2-wrapper   foo2oak foo2xqx-wrapper
foo2hiperc  foo2oak-wrapper foo2zjs
foo2hiperc-wrapper  foo2qpdlfoo2zjs-icc2ps@
foo2hp  foo2qpdl-wrapperfoo2zjs-pstops
foo2hp2600-wrapper  foo2slx foo2zjs-wrapper
foo2lavafoo2slx-wrapper foomatic-rip@

The pathnames matched by ">" and ">|" should be identical.



local keyword hides return code of command substitution

2015-09-22 Thread idallen
Configuration Information [Automatically generated, do not change]:
Machine: x86_64
OS: linux-gnu
Compiler: gcc
Compilation CFLAGS:  -DPROGRAM='bash' -DCONF_HOSTTYPE='x86_64' 
-DCONF_OSTYPE='linux-gnu' -DCONF_MACHTYPE='x86_64-pc-linux-gnu' 
-DCONF_VENDOR='pc' -DLOCALEDIR='/usr/share/locale' -DPACKAGE='bash' -DSHELL 
-DHAVE_CONFIG_H   -I.  -I../. -I.././include -I.././lib  -D_FORTIFY_SOURCE=2 -g 
-O2 -fstack-protector-strong -Wformat -Werror=format-security -Wall
uname output: Linux idallen-oak 3.19.0-28-generic #30-Ubuntu SMP Mon Aug 31 
15:52:51 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux
Machine Type: x86_64-pc-linux-gnu

Bash Version: 4.3
Patch Level: 30
Release Status: release

Description:
Adding a "local" keyword to a variable assignment hides the
return code of a command substitution.  Same problem in both
bash and dash shells.

The keyword may be operating as described in the man page,
but it is highly non-intuitive that adding it would do this.

The work-around is to use "local" to declare the variable first,
then do the command substitution assignment on another line and
check the return code there.

If the behaviour of "local" can't be changed, perhaps the man
page could warn about this?

Repeat-By:

Run this:

#!/bin/bash -u
# Using "local" keyword hides return code of command substitution.
# Same problem in both bash and dash shells.
# -Ian! D. Allen - idal...@idallen.ca - www.idallen.com
Myfunc () {
foo=$( false )
echo "return code should be 1: $?"
local bar=$( false )
echo "return code should be 1: $?"
}
Myfunc



history separates >| and 2>&1 tokens when recalled with !*

2016-04-21 Thread idallen
Configuration Information [Automatically generated, do not change]:
Machine: x86_64
OS: linux-gnu
Compiler: gcc
Compilation CFLAGS:  -DPROGRAM='bash' -DCONF_HOSTTYPE='x86_64' 
-DCONF_OSTYPE='linux-gnu' -DCONF_MACHTYPE='x86_64-pc-linux-gnu' 
-DCONF_VENDOR='pc' -DLOCALEDIR='/usr/share/locale' -DPACKAGE='bash' -DSHELL 
-DHAVE_CONFIG_H   -I.  -I../. -I.././include -I.././lib  -D_FORTIFY_SOURCE=2 -g 
-O2 -fstack-protector-strong -Wformat -Werror=format-security -Wall
uname output: Linux idallen-oak 4.2.0-35-generic #40-Ubuntu SMP Tue Mar 15 
22:15:45 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux
Machine Type: x86_64-pc-linux-gnu

Bash Version: 4.3
Patch Level: 42
Release Status: release

Description:
The history recall !* incorrectly pulls apart the >| and 2>&1
words, making them useless.

Repeat-By:
bash-4.3$ date >| /tmp/i
bash-4.3$ who !*
who > | /tmp/i
bash: syntax error near unexpected token `|'

bash-4.3$ date 2>&1
Thu Apr 21 19:24:46 EDT 2016
bash-4.3$ echo !*
echo 2 >& 1
2



man page confusion about array with no members: var=()

2016-07-13 Thread idallen
Configuration Information [Automatically generated, do not change]:
Machine: x86_64
OS: linux-gnu
Compiler: gcc
Compilation CFLAGS:  -DPROGRAM='bash' -DCONF_HOSTTYPE='x86_64' 
-DCONF_OSTYPE='linux-gnu' -DCONF_MACHTYPE='x86_64-pc-linux-gnu' 
-DCONF_VENDOR='pc' -DLOCALEDIR='/usr/share/locale' -DPACKAGE='bash' -DSHELL 
-DHAVE_CONFIG_H   -I.  -I../. -I.././include -I.././lib  -Wdate-time 
-D_FORTIFY_SOURCE=2 -g -O2 -fstack-protector-strong -Wformat 
-Werror=format-security -Wall
uname output: Linux idallen-oak 4.4.0-28-generic #47-Ubuntu SMP Fri Jun 24 
10:09:13 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux
Machine Type: x86_64-pc-linux-gnu

Bash Version: 4.3
Patch Level: 46
Release Status: release

Description:
The BASH man pags says "When there are no array members,
${name[@]} expands to nothing." and then later "An array variable
is considered set if a subscript has been assigned a value.".

The first sentence tells me that ${name[@]} is a valid use of a
variable that exists but has no members, but the second sentence
implies that if the array has no members it is considered "unset"
and thus ${name[@]} would not be a valid use of the name.

These are contradictory statements.  Using ${name[@]} with
no array members generates an "unbound variable" error under
"nounset"; it does not expand to "nothing".

The reason ${name[@]} expands to nothing is not because it's
a valid use of ${name[@]}, it's because any use of an unset
variable expands to nothing, unless, as I do, you run with
"nounset" enabled and it causes an error.

To fit current behaviour, the first man page sentence above should
be changed to say: When there are no array members, the array
name is considered unset and ${name[@]} will expand to nothing or
generate an "unbound variable" error under the "nounset" option.

I'd prefer that BASH change the behaviour of var=() to not give
an "unbound variable" error on ${name[@]}, but changing the man
page is probably easier than changing the current behaviour.

Repeat-By:
#!/bin/bash -u

# make BASH complain about unset variables
set -o nounset

echo 'ONE: set var= and try $var and ${var[@]} - both work without 
error'
unset var
var=
( echo "ONE: [$var]" )
( echo "ONE: [${var[@]}]" )

echo 'TWO: set var=() and try again - both fail with "unbound variable"'
unset var
var=()
( echo "TWO: [$var]" )
( echo "TWO: [${var[@]}]" )



built-in commands give no syntax error on trailing garbage

2016-09-14 Thread idallen
Configuration Information [Automatically generated, do not change]:
Machine: x86_64
OS: linux-gnu
Compiler: gcc
Compilation CFLAGS:  -DPROGRAM='bash' -DCONF_HOSTTYPE='x86_64' 
-DCONF_OSTYPE='linux-gnu' -DCONF_MACHTYPE='x86_64-pc-linux-gnu' 
-DCONF_VENDOR='pc' -DLOCALEDIR='/usr/share/locale' -DPACKAGE='bash' -DSHELL 
-DHAVE_CONFIG_H   -I.  -I../. -I.././include -I.././lib  -Wdate-time 
-D_FORTIFY_SOURCE=2 -g -O2 -fstack-protector-strong -Wformat 
-Werror=format-security -Wall
uname output: Linux idallen-oak 4.4.0-36-generic #55-Ubuntu SMP Thu Aug 11 
18:01:55 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux
Machine Type: x86_64-pc-linux-gnu

Bash Version: 4.3
Patch Level: 46
Release Status: release

Description:
Many built-in commands ignore trailing garbage instead of giving
a syntax error, and this leads newbies into making dumb mistakes
that they think work fine because of no error message, e.g.:

$ umask 0777 myfile   # should have been chmod
$ cd /usr /bin# goes to /usr not to intended /usr/bin

Commands should never ignore user input.  If it's there, someone
thinks it should be used.  Use it or please give error messages.

Repeat-By:
$ cd /bin this trailing garbage is ignored but should give an error

$ pushd /bin this trailing garbage is ignored but should give an error

$ umask 022 this trailing garbage is ignored but should give an error

$ help help this trailing garbage is ignored but should give an error

etc.

Fix:
Make built-in commands give error messages if given too many arguments.



PWD not made canonical on shell start

2017-05-23 Thread idallen
Configuration Information [Automatically generated, do not change]:
Machine: x86_64
OS: linux-gnu
Compiler: gcc
Compilation CFLAGS:  -DPROGRAM='bash' -DCONF_HOSTTYPE='x86_64' 
-DCONF_OSTYPE='linux-gnu' -DCONF_MACHTYPE='x86_64-pc-linux-gnu' 
-DCONF_VENDOR='pc' -DLOCALEDIR='/usr/share/locale' -DPACKAGE='bash' -DSHELL 
-DHAVE_CONFIG_H   -I.  -I../. -I.././include -I.././lib  -Wdate-time 
-D_FORTIFY_SOURCE=2 -g -O2 -fstack-protector-strong -Wformat 
-Werror=format-security -Wall
uname output: Linux idallen-oak 4.4.0-78-generic #99-Ubuntu SMP Thu Apr 27 
15:29:09 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux
Machine Type: x86_64-pc-linux-gnu

Bash Version: 4.3
Patch Level: 48
Release Status: release

Description:
In both BASH and DASH the shell variable $PWD is not always set
by the shell on start-up to be the actual absolute path to the
current directory.  If PWD is passed in via the environment, it
is used *as-is* as long as it is an absolute path and whatever
directory it resolves to is the *same* as the current directory.

This means you can pass in some crazy /././ and /../../../
pathnames via PWD and the shell will use them as-is.

I know that PWD can contain symlinks, if set with the "cd"
command and "physical" is turned off.   (And I see that "physical"
isn't even an option in DASH.)  But nothing documents how /././
and /../../ can ever appear in PWD, so these things shouldn't
be allowed to enter PWD via the environment.

As shown below, you can pass in values of PWD that cannot be set
using the "cd" command inside the shell itself.  The examples
below that are full of /././ and /../../ crap are especially
troubling, since there is no way to use the "cd" command to set
these values inside the shell, and the man page says that PWD
is set by the "cd" command, so having values in PWD that can't
be set using "cd" is wrong.

I think it a bug that /././ and /../../ pathnames passed in
via PWD are not cleaned up on shell start-up.  You could make a
case that a PWD containing symlinks should be allowed in from
the environment, (unless -o physical) but surely not /././
and /../../ in pathnames?  The shell should do the equivalent
of "cd ." to clean up PWD at start-up.

The man page doesn't say what happens with PWD if it is passed
in via the environment.  If you're going to keep the current
behaviour, please document it, since the environment allows messy
values in PWD that are unlike anything the shell does with the
"cd" command.  Not what I was expecting, at all.

As implemented, I now have to start every shell script that
uses $PWD before using "cd" with either 'cd "$(/bin/pwd)"' or
'set -o physical ; cd .' to get PWD into a usable state.

Repeat-By:

$ cat i.sh
#!/bin/bash -u
echo "$PWD"

$ unset PWD
$ printenv PWD
$ ./i.sh
/home/idallen

$ PWD=crap ./i.sh
/home/idallen

$ PWD=/./././././home/././././idallen/./././. ./i.sh
/./././././home/././././idallen/./././.

$ ln -s /home/idallen /tmp/foo
$ PWD=/tmp/foo ./i.sh
/tmp/foo
$ PWD=/../../../../tmp/foo ./i.sh
/../../../../tmp/foo