help-bash
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: how much are "historic" issues with test / [ still an issue


From: Chet Ramey
Subject: Re: how much are "historic" issues with test / [ still an issue
Date: Tue, 25 May 2021 11:04:13 -0400
User-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:78.0) Gecko/20100101 Thunderbird/78.10.2

On 5/25/21 7:47 AM, Christoph Anton Mitterer wrote:
Hey again.

Via the other thread I've recently stumbled over test/[’s -o and -a
options being deprecated for some reasons, as e.g. described in the
"Rationale" section of:
https://pubs.opengroup.org/onlinepubs/9699919799/utilities/test.html


I wondered how much shells (especially bash, but perhaps also dash if
someone coincidentally knows) are still affected by this?

The bash `test' implements the POSIX algorithm, which was first published
in the 1003.2 drafts, so bash has provided a way to avoid those problems
for at least 30 years.


1) > test "$1" -a "$2"
    > should be written as:
    > test "$1" && test "$2"

So AFAIU, the problem here is that whenever any user input ($var)
contains a string that might be taken as a operator (i.e. ( ! or
starting with -) ambiguous results could come out.

Historically, yes. The POSIX algorithm, being based on the number of
arguments, provides more determnistic execution.

The example given was $1 set to ! and $2 being empty, in which case, I
guess -a is taken as a string as if ! $var was written.

Not if the arguments are quoted. If you don't quote the arguments, you
never know what `test' is going to see in the first place.


But the result seems to be the same as with && ... and even if one
takes bash with has the unary -a FILE ... it doesn't seem to do a:
! ( -a FILE )

That case is covered by operator precedence parsing. The parens have a higher precedence than binary operators, so this returns a 0 status if
FILE doesn't exist. It's a convoluted way to write it, but it is different
from `! -a FILE' because the -a binary operator has a higher precedence
than `!' when three arguments are supplied.


2) Allegedly on "historical systems" (only?)
    > The two commands:
    > test "$1"
    > test ! "$1"
    should be written as:
    > test -n "$1"
    > test -z "$1"

Yes. You don't need to do that on POSIX systems because of the defined
behavior of test with one and two arguments.


Even more importantly for me, cases like:
    > test "$response" = "expected string"
    shall be written as:
    > test "X$response" = "Xexpected string"

I guess the leading X is simply to "escape" any possible meta-character
like ( ! or -, right ?

Historically, yes.


If one doesn't use more than 3 params, i.e. no parentheses -a -o, is
there any chance that a:
"$str1" op "str2"
could be still taken wrongly, if not adding the X?

For shells that use the POSIX algorithm, if OP is one of the binary
operators, no. The binary operators have higher predecence than `!' in
the three-argument case.

So are these still an issue with modern versions of bash (and dash,
etc.)?


At least the case of:
    > test -d $1 -o -d $2
seems to be "still" an issue if $1 is =

That falls into `historical algorithm' territory, since there are five
arguments.

You can rewrite as

        test -d "$1" || test -d "$2"
or
        [[ -d "$1" || -d "$2" ]]

and have the advantage of short-circuiting after the first test if it ends
up being true.


--
``The lyf so short, the craft so long to lerne.'' - Chaucer
                 ``Ars longa, vita brevis'' - Hippocrates
Chet Ramey, UTech, CWRU    chet@case.edu    http://tiswww.cwru.edu/~chet/



reply via email to

[Prev in Thread] Current Thread [Next in Thread]