autoconf-patches
[Top][All Lists]
Advanced

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

Re: Autoconf manual's coverage of signed integer overflow & portability


From: Paolo Bonzini
Subject: Re: Autoconf manual's coverage of signed integer overflow & portability
Date: Wed, 03 Jan 2007 09:38:15 +0100
User-agent: Thunderbird 1.5.0.9 (Macintosh/20061207)


The C Standard says that if a program has signed integer overflow its
behavior is undefined, and the undefined behavior can even precede the
overflow.  To take an extreme example:

@c Inspired by Robert Dewar's example in
@c <http://gcc.gnu.org/ml/gcc/2007-01/msg00038.html> (2007-01-01).
@example
if (password == expected_password)
  allow_superuser_privileges ();
else
  printf ("%d password mismatches\n", counter++);
@end example

@noindent
If @code{counter} is an @code{int} and a compiler can deduce that
@code{counter == INT_MAX} or that @code{counter} previously overflowed,
the C standard allows the compiler to optimize away the password test
and generate code that allows superuser privileges unconditionally.

I think this will only confuse the matter.

Hardly any code actually depends on wraparound arithmetic in cases like
these, so in practice these loop induction optimizations are almost
always useful.  However, edge cases in this area can cause problems.
For example:

@example
int j;
for (j = 1; 0 < j; j *= 2)

Why not j > 0?

  test (j);
@end example

@noindent
Here, the loop attempts to iterate through all powers of 2 that
@code{int} can represent, but some test versions of @acronym{GCC}

s/test versions of @acronym{GCC}/compilers/

optimize away the comparison to zero and thus generate an infinite loop,
under the argument that behavior is undefined on overflow.  As of this
writing this optimization is not done by any production version of
@acronym{GCC} with @option{-O2}, but it might be performed by more
aggressive @acronym{GCC} optimization options, or by other compilers.

s/or by/by future versions of @acronym{GCC}, or by/

If your code uses an expression like @code{(i * 2000) / 1000} and you
actually want the multiplication to wrap around reliably, put the
product into a temporary variable and divide that by 1000.  This
inhibits the algebraic optimization on many platforms.

This is a no-no. There's no reason why putting the product into a temporary variable would work (that is true for Ada, apparently). I'd suggest instead something like this:

int shift = 8 * (sizeof (long long) - sizeof (int));
return (int) (((long long) (i * 2000)) << shift >> shift) / 1000;

for which GCC at -O2 compiles the same code as the simpler "(i * 2000) / 1000" at -O2 -fwrapv.

If you need to port to platforms where signed integer overflow does not
reliably wrap around (e.g., due to hardware overflow checking, or to
highly aggressive optimizations), you should consider using
@acronym{GCC}'s @option{-ftrapv} option, which causes signed overflow to
raise an exception.

As -ftrapv hinders performance, however, you should also consider using it only for debugging purposes.

Paolo





reply via email to

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