[Cryptography] GCC bug 30475 (was Re: bounded pointers in C)

Jerry Leichter leichter at lrw.com
Fri May 2 14:34:48 EDT 2014


On May 2, 2014, at 8:44 AM, Benjamin Kreuter <brk7bx at virginia.edu> wrote:
> Consider this function:
> 
> int fact(int x) {
>  if (x <= 1) return 1;
>  else return x * fact(x - 1);
> }
> 
> Would you expect that to compile, or for it to be an error?  If
> potentially undefined behavior is a compiler error, that code cannot
> compile, since the multiplication might cause an overflow.
Oh, you're being way too modest.  x - 1 might underflow.  It's pretty much impossible to write an arithmetic operation that can be *guaranteed* not to cause undefined behavior for some inputs.  Combining values with 0 is safe - if x is an int, 0*x, 0+x, and x-0 have defined behavior; so does 1*x or x/1.  But you're never far from a cliff.  After:

int y = x + 0;

x == y is true, but memcmp(&x, &y, sizeof(int)) is undefined!  If the underlying arithmetic is 1's complement or sign and magnitude, there may - but need not necessarily - be two representations for 0, often written as +0 and -0; and the results of any particular operation involving -0 that produces a mathematically zero result may or may not be "normalized" to +0.  (Actually, to be accurate the result of memcmp() is undefined for two distinct reasons:  Not only might there be a -0 with a different representation, but an int could contain padding bits that don't contribute to its numeric value.)

You can rant about this all you like, but if you want to program (a) close to the machine - i.e., have efficient access to all machine facilities; and (b) write portable code, these kinds of tradeoffs are inevitable.

Before C was invented, you pretty much had to choose portability or performance.  C has done a remarkable job of providing high performance along with an extraordinary amount of portability.  Take a look at the machines on which NetBSD, written almost entirely in C, manages to run.

All this whining about undefined aspects of the language is just that - pointless whining.  The C Standard pins down as much as it can while still managing to efficiently support even some very obscure and oddball (but important to some constituents) architectures.

As I've said over and over on this thread:  Every implementation is free to define the "undefined" aspects of the Standard for itself.  In fact, simply supporting Posix interfaces pins down a number of them (the result of 1/0, for example).  It's perfectly legitimate to decide to restrict your code to environments where certain "undefined" aspects are pinned down in particular ways.  The fact is there are probably no practical, interesting pieces of code that are really fully portable.  It doesn't much bother anyone.

Yes, it would be a good thing if the C Standard provided some (probably optional) standardized ways to check whether operations have overflowed.  Apparently this isn't that big a deal for most coders or informal standards would have arisen years ago.  (stdint.h wasn't in the original C Standard, but there was a clear perceived need and multiple implementations of things kind of like it emerged, and eventually converged.  The converged version became the basis of stdint.h.)

Rather than whining about what the C Standard writers and compiler developers haven't given you ... develop some appropriate portable interfaces, implement them (in non-portable ways), and use them!  Maybe they'll even make it into the Standard some day.
                                                        -- Jerry

-------------- next part --------------
A non-text attachment was scrubbed...
Name: smime.p7s
Type: application/pkcs7-signature
Size: 4813 bytes
Desc: not available
URL: <http://www.metzdowd.com/pipermail/cryptography/attachments/20140502/8f35b82a/attachment.bin>


More information about the cryptography mailing list