ash: question about using test with '=' as $1
Joshua Judson Rosen
jrosen at harvestai.com
Mon Oct 5 14:51:42 UTC 2015
On 2015-10-04 13:49, Bastian Bittorf wrote:
> while discussing a shellsheck issue[1], i stumpled
> upon an interesting behaviour which is weird and
> i cannot find it to be a problem when reading POSIX[2]
> here, but all tested shells (ash,dash,bash) somehow
> break at this:
>
> user at box:~ x='='
> user at box:~ test -n "$x" -a 1 -eq 1
> ash: 1: unknown operand
>
> but this works:
>
> user at box:~ test -n "$x"
> user at box:~ echo $?
> 0
> user at box:~ test -z "$x"
> user at box:~ echo $?
> 1
>
> the problem is using -a or -o which
> is "unspecified" according to posix, but...really?
The problem is that you're actually not using "-a" (or "-o")
as operators; you're using "-a" in that example
as an *operand*, because the binary operator "="
is higher precedence than the unary operators. So,
you're asking test to evaluate this expression:
-n = -a
... with extra arguments on the end.
I get the same results if I replace your "-n" or "-a"
(or both of them) with any other strings, e.g.:
test foo = bar 1 -eq 1
Bash says "too many arguments"; busybox says "unknown operand",
which means the same thing.
> [1] https://github.com/koalaman/shellcheck/issues/489
> [2] http://pubs.opengroup.org/onlinepubs/9699919799/utilities/test.html
The "Application Usage" section of the POSIX man page that you cite
explains almost exactly the situation you're describing
as an example of how and why you need to "be extremely careful when
dealing with user-supplied input that could be confused with these
and other primaries and operators" :)
Because the string comparison binary primaries, '=' and "!=", have a higher
precedence than any unary primary in the greater than 4 argument case,
unexpected results can occur if arguments are not properly prepared. For
example, in:
test -d $1 -o -d $2
If $1 evaluates to a possible directory name of '=', the first three arguments
are considered a string comparison, which shall cause a syntax error when the
second -d is encountered.
Along with the solutions that are described there, consider:
test "X$x" != X -a 1 -eq 1
--
"Don't be afraid to ask (λf.((λx.xx) (λr.f(rr))))."
More information about the busybox
mailing list