GNU bug report logs - #23222
test: incorrect operator-precedence

Previous Next

Package: coreutils;

Reported by: Mattias Andrée <maandree <at> member.fsf.org>

Date: Tue, 5 Apr 2016 14:56:01 UTC

Severity: normal

Tags: confirmed, fixed

Done: Assaf Gordon <assafgordon <at> gmail.com>

Bug is archived. No further changes may be made.

Full log


View this message in rfc822 format

From: Mattias Andrée <maandree <at> kth.se>
To: Eric Blake <eblake <at> redhat.com>
Cc: 23222 <at> debbugs.gnu.org, Mattias Andrée <maandree <at> member.fsf.org>
Subject: bug#23222: test: incorrect operator-precedence
Date: Tue, 5 Apr 2016 20:36:07 +0200
[Message part 1 (text/plain, inline)]
On Tue, 5 Apr 2016 09:09:40 -0600
Eric Blake <eblake <at> redhat.com> wrote:

> tag 23222 confirmed
> thanks
> 
> On 04/05/2016 05:57 AM, Mattias Andrée wrote:
> > Failing test-case #1:
> > 
> > ./test -n -a -n
> > 
> > fails and outputs
> > 
> >   ./test: extra argument ‘-n’
> > 
> > Expected behaviour is silent success, as seen in
> > Bash's implementation.  
> 
> Thanks for the report.  POSIX indeed says that -a is a
> binary primary, and also says that
> "3 arguments:
>         If $2 is a binary primary, perform the binary
> test of $1 and
> $3." (http://pubs.opengroup.org/onlinepubs/9699919799/utilities/test.html)
> 
> So by that reading, coreutils MUST parse your expression
> as:
> 
> test \( -n \) -a \( -n \)
> 
> whereas it appears that coreutils has instead
> accidentally parsed it as:
> 
> test \( -n -a \) -n
> 
> Not everyday someone finds a real bug in 'test'!
> 
> That said, POSIX _also_ says that portable scripts MUST
> NOT use -a or -o; it is inherently ambiguous.
> 
> You are better off fixing your script to use:
> 
> test -n && test -n
> 
> whether or not someone is able to quickly patch
> coreutils' bug.

I'm not actually using -a, -o, (, ), and !. I just
noticed the bug by running some test-cases.

> 
> 
> > 
> > Explanation: -a has higher precedence than -n.  
> 
> Not quite true.  The POSIX rules state that -a is
> optional (non-XSI systems don't even have to have it),
> and that precedence has no bearing (rather, it is whether
> you have exactly three arguments that determines whether
> -a must be used in its role as a binary operator).
> 
> 
> > 
> > Failing test-case #2:
> > 
> > ./test ! '' -a ''
> > 
> > shall fail (exit value 1), but in this
> > implementation it succeeds.  
> 
> Sorry, but here, you're wrong.  POSIX states:
> 
> "4 arguments:
>         If $1 is '!', negate the three-argument test of
> $2, $3, and $4."
> 
> which means this parses as:
> 
> test ! \( '' -a '' \)
> 
> or as:
> 
> test ! \( \( '' \) -a \( '' \) \)
> 
> The negation of 'false and false' is true, so the exit
> status is correctly 0.
> 
> 
> > 
> > Explanation: ! has higher precedence than -a,  
> 
> Wrong.  As mentioned above, the rules are based not on
> precedence, but on how many operands are present.
> 

XSI-conformant systems shall use the following precedence
rules (highest to lowest), as documented (not quite as clearly)
in the POSIX specifications:

* parentheses

(1)

* string binary primaries

* unary non-string primaries

* algebraic binary primaries

(2)

* unary string primary

with

* (3)

* !

* -a

* -o

* (4)

in that order but not necessarily directly
followed by each other somewhere between
(1) and (2), and with other binary primitives
somewhere between (3) and (5).

The POSIX specification does indeed that that
the number of arguments shall determine the
precedence for 1 to 4 arguments. And the given
rules do conflict with XSI. But if we run

test \( \( ... \) \) instead of test it seems
only reasonable to use the XSI rules. Is it
too much to ask that test ... gives the same
result? Your implementation appear to be unaffected
if it is given extra parentheses in this way.
But it does evaluate test ! \( '' \) -a \( '' \)
as expected. It is very weird that
test ! \( '' \) -a \( '' \) and
test ! '' -a '' do not give the same result.

I believe that POSIX rule for 4 arguments shall
be disregarded. It is clearly only intended for
other binary operators than logical operators.
[Message part 2 (application/pgp-signature, inline)]

This bug report was last modified 6 years and 266 days ago.

Previous Next


GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.