Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 14 Feb 2006 12:04:02 +1100 (EST)
From:      Bruce Evans <bde@zeta.org.au>
To:        "M. Warner Losh" <imp@bsdimp.com>
Cc:        keramida@ceid.upatras.gr, arch@FreeBSD.org, stefanf@FreeBSD.org, cperciva@FreeBSD.org, des@des.no
Subject:   Re: [releng_6 tinderbox] failure on sparc64/sparc64
Message-ID:  <20060214083530.K22079@epsplex.bde.org>
In-Reply-To: <20060213.094336.118368793.imp@bsdimp.com>
References:  <20060213.002310.125802352.imp@bsdimp.com> <20060213082129.GA13997@flame.pc> <43F04494.4030900@freebsd.org> <20060213.094336.118368793.imp@bsdimp.com>

next in thread | previous in thread | raw e-mail | index | archive | help
[Someone wrote that certain accesses except via unsigned char are undefined.]

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

> In message: <43F04494.4030900@freebsd.org>
>            Colin Percival <cperciva@freebsd.org> writes:
> : Giorgos Keramidas wrote:
> : > On 2006-02-13 00:23, "M. Warner Losh" <imp@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



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20060214083530.K22079>