> An object may be the type of its last cast -- but it also can't
> exactly lose the benefit/cost of being cast to a pointer to an
> undefined type. As soon as you undefine the type of a pointer, it
> loses the remnant of ever having had the initial type in the first
> place.


Right, but that doesn't help you. For example:

int j=3D2;
double *d=3D(double *)(void *)&j;
*d=3D1.0;
printf("%d\n", j);

This can output 2. Even though '&j' lost all intness by the cast to =
'void *', it got 100% doubleness by the cast to 'double *'. The compiler =
can still assume that '*d' will not affect the value of 'j' because 'd' =
is a pointer to a type that is incompatible with 'j's type.

The rule still stands -- a modification through a pointer to one type =
can be assumed not to change the value of a variable of an incompatible =
type.

This is still what OpenSSL does when it passes an 'X509 **' as a 'char =
**'.
=20
> In K&R C, you couldn't cast to void *, that was first introduced in
> C89. You had to cast to char *, and then you could cast to some other
> type in order to make your array indexes jump sizeof(type),
> essentially (on 8-bit byte machines) referencing
> &array[(index)*(sizeof(type))].


The cast to 'char *' made things safe. However, once you cast it away =
from 'char *', it became dangerous again. There was no remnant of the =
'char *' cast. Yes, while it was a 'char *', it could alias anything, =
but as soon as you cast it to something else, it can no longer legally =
alias an incompatible type.

However, it should be safe to pass a 'char *' to a function that takes a =
'char *', and cast that parameter back to its real value in the =
function. For example, this should be legal:

int inc(int is_double, char *pointer)
{
if(is_double)
{
double *p=3D(double *) pointer;
*p=3D*p+1;
}
else
{
int *p=3D(int *) pointer;
*p=3D*p+1;
}
return 0;
}

---

int inc()
double j=3D1.0;
int i=3Dto_int(1, (char *) &j);
printf("%f", j);

That is because you are passing the function a compatible type, the =
compiler must assume a 'char *' might alias anything, and you are only =
dereferencing the pointer as a compatible type.

> Actually, what's broken is not allowing a large class of useful=20
> optimizations for the occasional code that chooses to invoke=20
> undefined behavior. That said, I do exactly what you suggest.=20
> I've had too much old code break horribly and subtly to find the=20
> optimizations worth the risk. So my 'official' position is not=20
> the same as my personal position.

=20
> 'occasional'? I've never examined any substantial program in C that
> doesn't invoke that -- even if just to be able to read data from disk
> into memory.


Many programs do aliasing correctly, following the rules that permit =
pointers to alias. However, I think it's a very fair point that nobody =
seems to totally understand what the rules *are*, which makes it hard to =
be sure you're following them.
=20
> An object is the type of the last cast -- but if it's ever cast to
> void *, it must be treated as if it were never any type before that.


The problem is precisely that it loses its association with the type it =
first was! If it kept its association with the first type, there'd be no =
problem.

Look at this code again:

int j=3D2;
double *d=3D(double *)(void *)&j;
*d=3D1.0;
printf("%d\n", j);

The *problem* is that '&j' has list its intness.

DS


__________________________________________________ ____________________
OpenSSL Project http://www.openssl.org
Development Mailing List openssl-dev@openssl.org
Automated List Manager majordomo@openssl.org