TIL: Some surprising code execution sources in bash

@yossarian There's something magical about the array invocation and numerical evaluation. It doesn't even need the arithmetic:

guess 'a[$(cat /etc/passwd > /tmp/pwned)]'
@yossarian wow wtf it also works for (( num == 42 ))?!
@yossarian ah interesting, [[ "${name}" == 42 ]] works correctly.
@postmodern @yossarian because that is a string comparison

@yossarian in this age it doesn't happen too often that someone says "surprising" in the title and whatever they're talking about is actually surprising in any way

but this genuinely is. and pretty scary

@yossarian regarding test -v - gould it be that with a[i] it checks if i-th element of the array exists?
@yossarian The use of '[[' is the problem. That's an evaluating comparison and is as dangerous as 'eval' (as shown). All scripts should be using just the single '['. Using '[[' is for compatibility with ancient shells.

@kees @yossarian Do we need to do something about this?

$ git grep '\[\[.*\]\]' origin/master -- ':*.sh' | wc --lines
1065

edit: there is some amount of false positives from sed regexes embedded in shell scripts. but also enough real cases

@vegard @kees @yossarian more like git grep '\[' ...

at least for me the `oh bummer' part was the observation that [ also behaves this way, because in bash it's a builtin. perhaps that can actually be considered a bug?

@kees @yossarian uh, good to know. I'm pretty sure at some point I've been told (maybe by some linting tool?) that [[ is preferrable to [.
@kees @yossarian https://www.shellcheck.net/wiki/SC2292 says "[[ .. ]] suppresses word splitting and globbing, supports a wider variety of tests, and is generally safer and better defined than [ .. ]"
Not enabled by default in current version, but I believe it was in the past.
ShellCheck: SC2292 – Prefer `[[ ]]` over `[ ]` for tests in Bash/Ksh.

@hanno @kees huh yeah, I guess that’s where I got the idea that [[ was preferred over [ from! thanks for finding that!

@kees this itself is a TIL for me, since I was taught/received that [[ is newer than [!

but also, is this always true? [ and ‘test’ will also use eval if the builtin version gets used first, but I don’t know the rules around when the builtins are used vs. not (for my interactive shell, they seem to always have precedence)

@kees @yossarian oh that's terrible though, because [ forks and [[ does not.
@kees @yossarian I tried with [ and it did not work. And 'type [' says "shell builtin" whereas 'type [[' says "shell keyword"
@kees @yossarian There is a problem with '[': it can confuse values coming from variables with operators. For example, suppose that you have
[ "$x" == a -a "$y" == b ]
Most of the time, it works. However, if $x is "!", it breaks. The correct version is
[ "x$x" == xa -a "x$y" == xb ]
Similarly,
[ -n "$x" -a -n "$y" ]
breaks if $x is "==".