[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20150410141925.GA9077@openwall.com>
Date: Fri, 10 Apr 2015 17:19:25 +0300
From: Solar Designer <solar@...nwall.com>
To: discussions@...sword-hashing.net
Subject: Re: [PHC] On type aliasing and similar issues
BTW, Samuel replied to me off-list suggesting that the php_mt_seed
example is most likely an icc bug, still present in icc 15 - he found
that the miscompile goes away by simply "swapping the order of vtype and
uint32_t []" in the source code, and that OTOH it still occurs even with
-fno-strict-aliasing.  Thanks, Samuel!
However, there being an icc bug doesn't tell us anything conclusive
about whether the source code is standards-compliant or not.
On Fri, Apr 10, 2015 at 03:59:05PM +0300, Alexander Cherepanov wrote:
> The direct use of member names is relatively clear -- it's alllowed and 
> it's plainly spelled out in a footnote in 6.5.2.3p3 (C99 and C11). The 
> use through pointers is also relatively clear -- it's prohibited, which 
> is plainly spelled out in gcc doc[1].
[...]
> Everything becomes more complicated when a member of a union is an 
> array. It's somewhat in-between these two cases and I'm not sure how 
> it's supposed to be treated.
What about uses like this:
typedef union {
	struct { uint32_t a1, a2; } a;
	uint64_t b;
} any_t;
void copy2(uint32_t *dst, uint32_t *src)
{
	((any_t *)dst)->b = ((any_t *)src)->b;
}
There's no access to members of the union through a pointer (nor even
through an array), but there's expected to be access through uint32_t *
pointers in the caller of copy2().  Would a compiler inlining copy2() be
guaranteed to do what the programmer expected (copy two 32-bit values,
potentially faster and assuming 64-bit alignment)?
Or with the opposite uses of the two integer types:
void add32x2(uint64_t *dst, uint64_t *src)
{
	((any_t *)dst)->a.a1 += ((any_t *)src)->a.a1;
	((any_t *)dst)->a.a2 += ((any_t *)src)->a.a2;
}
where the caller is expected to access through uint64_t * pointers.
(Of course, this example is sensitive to byte order - or rather, to the
order of 32-bit halves in a 64-bit word.)
> Side note: not much have changed between C89 and C99 in this question. 
> Accessing a wrong member in a union is an implementation-defined 
> behavior in C89 but a footnote in 3.3.2.3 implies that the reason for 
> this is indeterminate byte order. OTOH this behavior is defined in C99 
> but the byte order is still not specified. Hence a strictly conforming 
> program shouldn't use it anyway.
There are many use cases where byte order does not matter, such as when
implementing a maybe-faster memset() or memcpy() alike that would use a
wider data type (as long as alignment and total size permit).
Thanks!
Alexander
Powered by blists - more mailing lists