[releng_6 tinderbox] failure on sparc64/sparc64

Bruce Evans bde at zeta.org.au
Mon Feb 13 17:04:49 PST 2006


[Someone wrote that certain accesses except via unsigned char are undefined.]

On Mon, 13 Feb 2006, M. Warner Losh wrote:

> In message: <43F04494.4030900 at freebsd.org>
>            Colin Percival <cperciva at freebsd.org> writes:
> : Giorgos Keramidas wrote:
> : > On 2006-02-13 00:23, "M. Warner Losh" <imp at bsdimp.com> wrote:
> : >> 	struct foo foo;
> : >> 	uint32_t value[sizeof(foo) / sizeof(uint32_t)];
> : >>
> : >> 	memcpy(value, &foo);
> : >> 	// write out value one 32-bit word at a time
> : >>
> : >> Is that right?  Or at least 'proper' here means defined.
> : >
> : > AFAIK, yes.
> :
> : I agree that the behaviour of the above code is defined, but
> : I'd be much happier if value[] was defined to be an array of
> : length ((sizeof(foo) - 1) / sizeof(uint32_t) + 1), just in
> : case sizeof(foo) happens to not be a multiple of 4.  :-)

The behaviour of the above code is highly undefined.  There is no
`size' arg in the call to memcpy(), and fixing this alone leaves various
bugs and a complicated analysis to show that the behaviour is not
completely undefined.  The C standard only explicitly defines copying
from an object _to_ an array of unsigned char.  That copying back
doesn't give undefined behaviour is only implicitly defined.  The
above is much further from being explictly defined since it copies
essentially random bits _from_ a nameless intermediate array of unsigned
char to another object.  The behaviour would certainly be undefined for
most types of final object since there may be trap bits in the final
object, or it might just be implementation defined and not what is wanted
because there are non-trap padding bits in the final object.  However,
uint32_t doesn't have any padding bits, so it may be possible to show
that the behaviour of accessing the final object is defined (and useful).
I think this is equivalent to showing that the behaviour of the following
is defined:

 	auto uint32_t value;

 	value = 0;		/* undefined without this? */
 	memset(&value, random(), 1);
 	value++;

> It won't matter given how I'm going to fix this problem...

Why not just access the object as an array of unsigned chars as someone
wrote?  Write it out 1 unsigned char at a time for the simple version.
This avoids the complications.

Bruce


More information about the freebsd-arch mailing list