Out-of-bounds pointers

Chris Torek chris at mimsy.UUCP
Sun Oct 8 01:22:36 AEST 1989


[original question was about code similar to

	int array[K];
	p = &array[0];	/* ok */
	p--;		/* invalid */
]

>In article <217 at bbxsda.UUCP>, scott at bbxsda.UUCP (Scott Amspoker) writes:
>>We just got through an *extremely* long thread in comp.lang.c regarding
>>this issue ...

Actually, that thread was arguing about the invalid pointer value produced
by freeing a valid malloc()-derived pointer.  These are in fact entirely
different things: the freed pointer became invalid by the freeing action,
even though its bit pattern did not change, while the pointer above became
invalid by a pointer-arithmetic operation (which presumably changed its
bit pattern).

In article <2322 at munnari.oz.au> ok at cs.mu.oz.au (Richard O'Keefe) writes:
>I participated in that thread.  Basically it fizzled out because it was
>quite clear that the restriction isn't going to go away, so there wasn't
>any point in talking further.  But it also became clear that the 80286
>and 80386 are *NOT* examples of the problem; you wouldn't do pointer
>comparisons or pointer arithmetic in a segment register on an 80286
>because you _can't_.

Actually, in huge model, p-- really does do arithmetic on a value that
might be automatically reloaded into a segment register.  For instance,

	void f(void) {
		extern char foo[];
		extern int g(int);
		register char *p = foo + g(0);

		while (p != foo + g(1)) p--; /* strange timing loop, perhaps */
		*p++ = 'a'; *p++ = 'b'; *p = 'c';
	}

is as likely to use `es:di' for p as any other register pair (after
all, it is *a* pointer, and is the *only* pointer, and is used *as a*
pointer).  The comparison and decrement are in fact better done from
memory or from si:di, but some compilers are likely to simply say
`this looks like a pointer; we are in huge model; use es:di'.

>You can, if necessary, make your array one element longer than you need.

This is in fact the only certain solution for

	for (p = &array[K]; --p >= array;)

(i.e., change it to

	some_type array_[K+1];		/* dummy element at 0 */
	#define array (array_ + 1)	/* subscript range [-1..K-1] */
	for (p = &array[K]; --p >= array;)

or something equivalent).  Otherwise, if some_type is, e.g.,

	typedef struct enormous { char a[60000]; } sometype;

the operation `--p' will subtract 60,000 bytes from p on a VAX or Sun;
this could easily produce an underflow (32k of text, e.g.).  On a VAX,
it is possible to trap on integer underflow, including pointer
underflow, so you could rig a system to produce a runtime trap here.
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
Domain:	chris at cs.umd.edu	Path:	uunet!mimsy!chris



More information about the Comp.std.c mailing list