DASH Shell discussions
 help / color / mirror / Atom feed
* test incorrectly rejecting valid expression with confusing ! placement
@ 2013-08-24 14:01 Harald van Dijk
  2013-08-26 11:19 ` Thorsten Glaser
  2013-09-04  1:56 ` Herbert Xu
  0 siblings, 2 replies; 9+ messages in thread
From: Harald van Dijk @ 2013-08-24 14:01 UTC (permalink / raw)
  To: dash

Hi,

Now that Herbert fixed the reported crash in test (in a far simpler
manner than I had suggested, which I like), I did some more testing, and
came across one case that does not currently work, and did not work in
the past, but is perfectly valid:

$ src/dash -c 'test ! ! = !'
src/dash: 1: test: =: unexpected operator

POSIX requires special behaviour for four-argument tests:

4 arguments:
  If $1 is '!', negate the three-argument test of $2, $3, and $4.
  [...]

so this is supposed to evaluate as the negation of test ! = !. That test
does work properly in dash.

There are also some cases where test gives incorrect results when
combining ! with -o, but ( ), -a and -o have been obsoleted in favour of
the built-in shell operators ( ), && and ||, so I am not sure if that is
worth fixing. Details anyway:

$ src/dash -c 'test ! -o !'
src/dash: 1: test: -o: unexpected operator

This is covered by the special rule for three arguments, where the
second argument is a binary operator. -o is a boolean binary operator,
but a binary operator nonetheless, so this should test whether the two !
arguments are empty strings.

$ src/dash -c 'test ! "" -o !'; echo $?
0

This is covered by the special rule for four arguments, there ! as the
first argument evaluates the remaining three-argument test and negates
the result. In this special case, ! does not have higher precedence than
-o, so the correct exit status is 1, which bash's test gives.

Cheers,
Harald

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: test incorrectly rejecting valid expression with confusing ! placement
  2013-08-24 14:01 test incorrectly rejecting valid expression with confusing ! placement Harald van Dijk
@ 2013-08-26 11:19 ` Thorsten Glaser
  2013-08-26 16:24   ` Harald van Dijk
  2013-09-04  1:56 ` Herbert Xu
  1 sibling, 1 reply; 9+ messages in thread
From: Thorsten Glaser @ 2013-08-26 11:19 UTC (permalink / raw)
  To: dash

Harald van Dijk dixit:

>$ src/dash -c 'test ! ! = !'
>src/dash: 1: test: =: unexpected operator
>
>POSIX requires special behaviour for four-argument tests:

Right but…

>There are also some cases where test gives incorrect results when
>combining ! with -o

… ‘-o’ is XSI, not POSIX. Do not expect…

>$ src/dash -c 'test ! "" -o !'; echo $?

… this to work.

>This is covered by the special rule for four arguments, there ! as the
>first argument evaluates the remaining three-argument test and negates
>the result. In this special case, ! does not have higher precedence than
>-o, so the correct exit status is 1, which bash's test gives.

Only for a shell implementing the XSI ‘-o’ for POSIX test.
You shouldn’t use -o anyway as it’s deprecated.

bye,
//mirabilos
-- 
FWIW, I'm quite impressed with mksh interactively. I thought it was much
*much* more bare bones. But it turns out it beats the living hell out of
ksh93 in that respect. I'd even consider it for my daily use if I hadn't
wasted half my life on my zsh setup. :-) -- Frank Terbeck in #!/bin/mksh


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: test incorrectly rejecting valid expression with confusing ! placement
  2013-08-26 11:19 ` Thorsten Glaser
@ 2013-08-26 16:24   ` Harald van Dijk
  0 siblings, 0 replies; 9+ messages in thread
From: Harald van Dijk @ 2013-08-26 16:24 UTC (permalink / raw)
  To: dash

On 26/08/13 13:19, Thorsten Glaser wrote:
> Harald van Dijk dixit:
> 
>> $ src/dash -c 'test ! ! = !'
>> src/dash: 1: test: =: unexpected operator
>>
>> POSIX requires special behaviour for four-argument tests:
> 
> Right but…
> 
>> There are also some cases where test gives incorrect results when
>> combining ! with -o
> 
> … ‘-o’ is XSI, not POSIX. Do not expect…
>
>> $ src/dash -c 'test ! "" -o !'; echo $?
> 
> … this to work.
>
>> This is covered by the special rule for four arguments, there ! as the
>> first argument evaluates the remaining three-argument test and negates
>> the result. In this special case, ! does not have higher precedence than
>> -o, so the correct exit status is 1, which bash's test gives.
> 
> Only for a shell implementing the XSI ‘-o’ for POSIX test.

That is correct, but dash is such a shell. It attempts to implement -o,
-a, and \( ... \), and does so mostly correctly.

> You shouldn’t use -o anyway as it’s deprecated.

Indeed. I made a note that it has been obsoleted. I wrote:
> There are also some cases where test gives incorrect results when
> combining ! with -o, but ( ), -a and -o have been obsoleted in favour of
> the built-in shell operators ( ), && and ||, so I am not sure if that is
> worth fixing.

Even if it had not been obsoleted, it would be better not to use -a and
-o. In fact, I have trouble imagining why ! has not also been obsoleted
in favour of a simple logical negation of the test (test x != y instead
of test ! x == y, which is only possible for some of the tests), or the
shell's built-in ! (! test x == y instead of test ! x == y, which is
always possible).

Cheers,
Harald

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: test incorrectly rejecting valid expression with confusing ! placement
  2013-08-24 14:01 test incorrectly rejecting valid expression with confusing ! placement Harald van Dijk
  2013-08-26 11:19 ` Thorsten Glaser
@ 2013-09-04  1:56 ` Herbert Xu
  2013-09-04  2:38   ` Eric Blake
  2014-09-28 10:42   ` Herbert Xu
  1 sibling, 2 replies; 9+ messages in thread
From: Herbert Xu @ 2013-09-04  1:56 UTC (permalink / raw)
  To: Harald van Dijk; +Cc: dash

Harald van Dijk <harald@gigawatt.nl> wrote:
> Hi,
> 
> Now that Herbert fixed the reported crash in test (in a far simpler
> manner than I had suggested, which I like), I did some more testing, and
> came across one case that does not currently work, and did not work in
> the past, but is perfectly valid:
> 
> $ src/dash -c 'test ! ! = !'
> src/dash: 1: test: =: unexpected operator

Agreed.
 
> $ src/dash -c 'test ! -o !'
> src/dash: 1: test: -o: unexpected operator

Nope, the rule is quite clear that it only applies to binary
primaries, not operators.  -o is an operator.

Cheers,
-- 
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: test incorrectly rejecting valid expression with confusing ! placement
  2013-09-04  1:56 ` Herbert Xu
@ 2013-09-04  2:38   ` Eric Blake
  2013-09-04  3:20     ` Herbert Xu
  2014-09-28 10:42   ` Herbert Xu
  1 sibling, 1 reply; 9+ messages in thread
From: Eric Blake @ 2013-09-04  2:38 UTC (permalink / raw)
  To: Herbert Xu; +Cc: Harald van Dijk, dash

[-- Attachment #1: Type: text/plain, Size: 1590 bytes --]

On 09/03/2013 07:56 PM, Herbert Xu wrote:
> Harald van Dijk <harald@gigawatt.nl> wrote:
>> Hi,
>>
>> Now that Herbert fixed the reported crash in test (in a far simpler
>> manner than I had suggested, which I like), I did some more testing, and
>> came across one case that does not currently work, and did not work in
>> the past, but is perfectly valid:
>>
>> $ src/dash -c 'test ! ! = !'
>> src/dash: 1: test: =: unexpected operator
> 
> Agreed.
>  
>> $ src/dash -c 'test ! -o !'
>> src/dash: 1: test: -o: unexpected operator
> 
> Nope, the rule is quite clear that it only applies to binary
> primaries, not operators.  -o is an operator.

Huh?
http://pubs.opengroup.org/onlinepubs/9699919799/utilities/test.html
states that there are only two operators "!" and "()", and specifically
mentions that -a and -o are binary primaries:

expression1 -a  expression2
    [OB XSI] [Option Start]
    True if both expression1 and expression2 are true; otherwise, false.
The -a binary primary is left associative. It has a higher precedence
than -o. [Option End]
expression1 -o  expression2
    [OB XSI] [Option Start]
    True if either expression1 or expression2 is true; otherwise, false.
The -o binary primary is left associative. [Option End]

"test ! -o !" is a three-argument test, where $2 (-o) is a binary
primary, so it is the binary test of $1 and $3, and the end result is an
exit status of 0.  Bash and ksh get it right, dash fails.

-- 
Eric Blake   eblake redhat com    +1-919-301-3266
Libvirt virtualization library http://libvirt.org


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 621 bytes --]

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: test incorrectly rejecting valid expression with confusing ! placement
  2013-09-04  2:38   ` Eric Blake
@ 2013-09-04  3:20     ` Herbert Xu
  2013-09-04  5:03       ` Herbert Xu
  0 siblings, 1 reply; 9+ messages in thread
From: Herbert Xu @ 2013-09-04  3:20 UTC (permalink / raw)
  To: Eric Blake; +Cc: Harald van Dijk, dash

On Tue, Sep 03, 2013 at 08:38:16PM -0600, Eric Blake wrote:
>
> http://pubs.opengroup.org/onlinepubs/9699919799/utilities/test.html
> states that there are only two operators "!" and "()", and specifically
> mentions that -a and -o are binary primaries:

Well, a primary is usually something that cannot be reduced
further when discussing syntax.  As both -a and -o take expressions
on either side, it is highly unusual to designate them as primaries
instead of operators.

Also, in the rationale it clearly states that -a/-o are operators
and not primaries.

In any case, dash does not claim XSI conformance, so we're at
liberty to choose the most suitable implementation of an existing
feature that we inherited from BSD.
 
> "test ! -o !" is a three-argument test, where $2 (-o) is a binary
> primary, so it is the binary test of $1 and $3, and the end result is an
> exit status of 0.  Bash and ksh get it right, dash fails.

Both zsh and posh do it like dash:

$ zsh -c 'test ! -o !'; echo $?
zsh:test:1: too many arguments
1
$ zsh -c 'test ! = !'; echo $?
0
$

Cheers,
-- 
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: test incorrectly rejecting valid expression with confusing ! placement
  2013-09-04  3:20     ` Herbert Xu
@ 2013-09-04  5:03       ` Herbert Xu
  2013-09-04 12:09         ` Eric Blake
  0 siblings, 1 reply; 9+ messages in thread
From: Herbert Xu @ 2013-09-04  5:03 UTC (permalink / raw)
  To: Eric Blake; +Cc: Harald van Dijk, dash

On Wed, Sep 04, 2013 at 01:20:00PM +1000, Herbert Xu wrote:
>  
> > "test ! -o !" is a three-argument test, where $2 (-o) is a binary
> > primary, so it is the binary test of $1 and $3, and the end result is an
> > exit status of 0.  Bash and ksh get it right, dash fails.
> 
> Both zsh and posh do it like dash:
> 
> $ zsh -c 'test ! -o !'; echo $?
> zsh:test:1: too many arguments
> 1
> $ zsh -c 'test ! = !'; echo $?
> 0
> $

Another case in point is 'test ! = -o a', here bash differs with
every other shell installed on my system, which all return 0, just
like dash.

Cheers,
-- 
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: test incorrectly rejecting valid expression with confusing ! placement
  2013-09-04  5:03       ` Herbert Xu
@ 2013-09-04 12:09         ` Eric Blake
  0 siblings, 0 replies; 9+ messages in thread
From: Eric Blake @ 2013-09-04 12:09 UTC (permalink / raw)
  To: Herbert Xu; +Cc: Harald van Dijk, dash, Austin Group

[-- Attachment #1: Type: text/plain, Size: 1590 bytes --]

[adding the Austin Group]

On 09/03/2013 11:03 PM, Herbert Xu wrote:
> On Wed, Sep 04, 2013 at 01:20:00PM +1000, Herbert Xu wrote:
>>  
>>> "test ! -o !" is a three-argument test, where $2 (-o) is a binary
>>> primary, so it is the binary test of $1 and $3, and the end result is an
>>> exit status of 0.  Bash and ksh get it right, dash fails.
>>
>> Both zsh and posh do it like dash:
>>
>> $ zsh -c 'test ! -o !'; echo $?
>> zsh:test:1: too many arguments
>> 1
>> $ zsh -c 'test ! = !'; echo $?
>> 0
>> $
> 
> Another case in point is 'test ! = -o a', here bash differs with
> every other shell installed on my system, which all return 0, just
> like dash.

GNU coreutils behaves like bash; the POSIX wording justifies bash:

4 arguments:

        If $1 is '!', negate the three-argument test of $2, $3, and $4.

        [OB XSI] [Option Start] If $1 is '(' and $4 is ')', perform the
two-argument test of $2 and $3. [Option End]  On systems that do not
support the XSI option, the results are unspecified if $1 is '(' and $4
is ')'.

        Otherwise, the results are unspecified.

That is, "test ! = -o a" should be parsed as "test ! \( = -o a \)"
(bash's behavior, per the first bullet), not "test \( ! = \) -o a"
(ksh's behavior, per the third bullet).

Yet another reason why the XSI -a and -o make the parsing precedence of
test a pain to decipher.  Do we need to open yet another bug against
POSIX to allow for ksh's behavior?

-- 
Eric Blake   eblake redhat com    +1-919-301-3266
Libvirt virtualization library http://libvirt.org


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 621 bytes --]

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: test incorrectly rejecting valid expression with confusing ! placement
  2013-09-04  1:56 ` Herbert Xu
  2013-09-04  2:38   ` Eric Blake
@ 2014-09-28 10:42   ` Herbert Xu
  1 sibling, 0 replies; 9+ messages in thread
From: Herbert Xu @ 2014-09-28 10:42 UTC (permalink / raw)
  To: Harald van Dijk; +Cc: dash

On Wed, Sep 04, 2013 at 11:56:29AM +1000, Herbert Xu wrote:
> Harald van Dijk <harald@gigawatt.nl> wrote:
> > Hi,
> > 
> > Now that Herbert fixed the reported crash in test (in a far simpler
> > manner than I had suggested, which I like), I did some more testing, and
> > came across one case that does not currently work, and did not work in
> > the past, but is perfectly valid:
> > 
> > $ src/dash -c 'test ! ! = !'
> > src/dash: 1: test: =: unexpected operator
> 
> Agreed.

This case is now fixed by the following patch:

commit 4f7e4c8201e580b9d31c09d8a484741072033c01
Author: Herbert Xu <herbert@gondor.apana.org.au>
Date:   Sun Sep 28 18:40:18 2014 +0800

    [BUILTIN] Correctly handle test ! ! = !
    
    This patch adds a special case in testcmd for the 4-argument
    expression beginning with a !.  Without this ! ! = ! is deemed
    a syntax error, which breaks POSIX.
    
    Note that this special case does not extend down into subexpressions
    so if ! ! = ! is used inside parentheses then a syntax error will
    still occur as before.
    
    Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>

diff --git a/ChangeLog b/ChangeLog
index a466a7f..7345144 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+2014-09-28  Herbert Xu <herbert@gondor.apana.org.au>
+
+	* Correctly handle test ! ! = !.
+
 2014-09-26  Herbert Xu <herbert@gondor.apana.org.au>
 
 	* Small optimisation of command -pv change.
diff --git a/src/bltin/test.c b/src/bltin/test.c
index baa91a5..458e9f5 100644
--- a/src/bltin/test.c
+++ b/src/bltin/test.c
@@ -177,7 +177,7 @@ testcmd(int argc, char **argv)
 {
 	const struct t_op *op;
 	enum token n;
-	int res;
+	int res = 1;
 
 	if (*argv[0] == '[') {
 		if (*argv[--argc] != ']')
@@ -185,11 +185,12 @@ testcmd(int argc, char **argv)
 		argv[argc] = NULL;
 	}
 
+recheck:
 	argv++;
 	argc--;
 
 	if (argc < 1)
-		return 1;
+		return res;
 
 	/*
 	 * POSIX prescriptions: he who wrote this deserves the Nobel
@@ -209,6 +210,9 @@ testcmd(int argc, char **argv)
 			argv[--argc] = NULL;
 			argv++;
 			argc--;
+		} else if (!strcmp(argv[0], "!")) {
+			res = 0;
+			goto recheck;
 		}
 	}
 
@@ -216,7 +220,7 @@ testcmd(int argc, char **argv)
 
 eval:
 	t_wp = argv;
-	res = !oexpr(n);
+	res ^= oexpr(n);
 	argv = t_wp;
 
 	if (argv[0] != NULL && argv[1] != NULL)

Cheers,
-- 
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt

^ permalink raw reply related	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2014-09-28 10:43 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-08-24 14:01 test incorrectly rejecting valid expression with confusing ! placement Harald van Dijk
2013-08-26 11:19 ` Thorsten Glaser
2013-08-26 16:24   ` Harald van Dijk
2013-09-04  1:56 ` Herbert Xu
2013-09-04  2:38   ` Eric Blake
2013-09-04  3:20     ` Herbert Xu
2013-09-04  5:03       ` Herbert Xu
2013-09-04 12:09         ` Eric Blake
2014-09-28 10:42   ` Herbert Xu

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox