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


Message #10 received at control <at> debbugs.gnu.org (full text, mbox):

From: Eric Blake <eblake <at> redhat.com>
To: Mattias Andrée <maandree <at> member.fsf.org>,
 23222 <at> debbugs.gnu.org
Subject: Re: bug#23222: test: incorrect operator-precedence
Date: Tue, 5 Apr 2016 09:09:40 -0600
[Message part 1 (text/plain, inline)]
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.


> 
> 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.

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

[signature.asc (application/pgp-signature, attachment)]

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.