Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 30 Jun 2011 19:06:03 +0200
From:      Stefan Esser <se@freebsd.org>
To:        freebsd-standards@freebsd.org
Subject:   Re: Fwd: [RFC] Consistent numeric range for "expr" on all architectures
Message-ID:  <4E0CACFB.8040906@freebsd.org>
In-Reply-To: <20110630164653.GA82980@zim.MIT.EDU>
References:  <4E09AF8E.5010509@freebsd.org> <4E0B860E.50504@freebsd.org> <20110630164653.GA82980@zim.MIT.EDU>

next in thread | previous in thread | raw e-mail | index | archive | help
Am 30.06.2011 18:46, schrieb David Schultz:
> On Wed, Jun 29, 2011, Stefan Esser wrote:
>> My suggestion is to make the following modifications to expr:
>>
>> 1) Always compute with 64 bit range and overflow checks enabled. This
>>    means, that the "-e" option is always assumed.
>>
>> 2) Continue to support the "-e" option as a NOP for compatibility with
>>    scripts that knew about that FreeBSD extension.
> 
> Using 64-bit signed integer arithmetic consistently in expr sounds
> like a reasonable idea.  There's no reason shell scripts ought to
> be exposed to architectural details.

Yes, especially when you move them from e.g. amd64 to i386 ...

> There are two problems, however.  First, the implementation
> doesn't do this: it uses intmax_t, which has platform-dependent
> width, at least in theory.  Second, it sounds like POSIX doesn't

Yes, but it seems that intmax_t is guaranteed to be at least 64bit wide.

> allow this (although I don't know where this requirement comes
> from):
> 
> | r96367 | wollman | 2002-05-10 18:59:29 -0400 (Fri, 10 May 2002) | 5 lines
> | 
> | The response to my POSIX interpretation request says that `expr'
> | is required to be oblivious to overflow and to use the data type `long'.
> | (Division by zero is undefined in ISO C so it's still OK to check for it
> | here.)  Add a new `-e' flag to get the old, more useful behavior.

Well, that's the frustrating part: I had implemented 64bit range in expr
back in 2000, but this extended range (on 32bit archs) has been made
optional, some two years later with the commit message you quote.

In between, a number of people were hurt by scripts that silently
truncated numeric operands or results, and during a mail exchange in
that context, the above requirement was said to not really apply.

The reasoning is, that overflow beyond the range of signed long leads to
unspecified behaviour. And one possibility to deal with unspecified
behaviour it to just return the "correct" result without wrap-aroung.

The range check is also possible in that case, AFAIK. Once you are
outside the specified range, POSIX allows extensions that do just what I
propose (and what already was in FreeBSD, 10 years ago).

> Nevertheless, moving to int64_t arithmetic by default seems like a
> good idea, with low potential for complications.

On amd64 and other 64 bit architectures the numeric range already is 64bit.

> Overflow checking is a separate concern, and one that is more
> likely to cause problems.  I'd be more careful about changing the
> default behavior there, because some scripts might rely on modular
> arithmetic without overflow checks.

You cannot portably rely in overflow, since you have no guarantee that
overflow occurs at a specific boundary.

> Another thing that is likely to cause confusion is expr(1)
> behaving differently from the shell builtin, and differently from
> the shell's arithmetic.  Above all else, I suggest trying to make
> everything consistent...perhaps talk to jilles@ about the shell
> side of things.

My change in 2000 made the shell builtin do 64bit arithmetic as well (in
fact, the shell build just included the expr.y file ...).

But there is no expr builtin anymore, so there is no risk here ;-)

Regards, STefan



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?4E0CACFB.8040906>