Out-of-bounds pointers

david.f.prosser dfp at cbnewsl.ATT.COM
Thu Oct 12 05:22:41 AEST 1989


In article <976 at crdos1.crd.ge.COM> davidsen at crdos1.UUCP (bill davidsen) writes:
>  Consider: a program is going to read some LARGE number of values in
>the range 30000-30006. It wants to count the number of occurences of
>each value. Therefore:
>	long ShortVect[10] = {0,0,0,0,0,0,0,0,0,0}, *Ptr, Val;
>	
>	Ptr = &ShortVect[-30000];
>	while ((Val = MyRead()) > 0) Ptr[Val]++;
>
>  Note that by creating the pointer to an invalid address we now can add
>the value as a subscript. The address modified is *always* valid (if the
>input is in range), the vector doesn't need to be 30007 in length, and
>you don't have to subtract 30000 each time.

This relies on the "recovery" of the pointer value through pointer
arithmetic on the invalid value.  On architectures in which overflow
and underflow on pointers produce quiet wrap-around, you are correct
that this sort of approach will work.

>  I make no claim that this is the only way to do this, simple that
>there are programs around which actually do use this trick (I saw it in
>a net program). I submit that this is neither sloppy programming or
>meaningless, and that it is "not illegal" by K&R 1st Ed. It's a trick to
>save some space and CPU, something anyone on a small machine tries to do.

>|  I have no idea what you mean by "prevailing practice".  

>  Prevailing practice means what it says, that before compilers were
>modified to make it illegal such code would work on most machines, such
>as Sun, Vax, PC, Cray, PDP-11, etc. I think that fairly represents at
>least 80% of the machines and users running pre-ANSI C.

I claim that most (all?) of these can be caused to produce some sort
of "noise" on overflow and/or underflow, most likely raising a
computational exception signal.  While, by default, some (all?)
silently wrap, there has been no guarantee that this behavior must
occur.

As such, the prevailing practice does not guarantee that this approach
will behave as desired.

The X3J11 committee tried its best to mean it when it gave guarantees.
It is entirely due to this sort of issue that asynchronous signal
handling is so restrictive.

This doesn't mean that you shouldn't write code like the above, just
that you write it knowing what is required for an architecture to
guarantee this not-strictly-portable approach.

There are portability trade-offs made in virtually all C programs,
unfortunately many are simply not recognized as such by the programmer.

Dave Prosser	...not an official X3J11 answer...



More information about the Comp.std.c mailing list