Live data from Hacker News

The Strict Aliasing Situation Is Pretty Bad

blog.regehr.org

31–40 of 70 posts

Re: The Strict Aliasing Situation Is Pretty Bad

#31
post #25

Earlier quoted context omitted.

If we talk in terms of concepts that exist in the C standard, we would say that you can't cast an object to pointer-to-X unless your pointer actually points to an X. The reason your example is illegal is that you are casting to pointer-to-"struct derived", but the thing being pointed to is not actually a "struct derived." The "physical subtyping" pattern works because the C standard says that a pointer to a struct, s…

Looks like your other comment hit the max reply depth so this will need to finish up, but in any case I don't agree with your reading of the vice versa.

Replying to myself because depth limit.

Let me try to think of a good way to update the post to capture this better...

Re: The Strict Aliasing Situation Is Pretty Bad

#32
post #31
post #25

Earlier quoted context omitted.

Looks like your other comment hit the max reply depth so this will need to finish up, but in any case I don't agree with your reading of the vice versa.

Replying to myself because depth limit. Let me try to think of a good way to update the post to capture this better...

There isn't actually a depth limit (or if there is we haven't hit it yet :). HackerNews just hides the "reply" link for 5 minutes or so to cool down flamewars.

You can work around this by clicking on the link for the post itself (ie. "3 minutes ago") which allows you to reply immediately.

Re: The Strict Aliasing Situation Is Pretty Bad

#33

Earlier quoted context omitted.

> Did you even make sure the memory was aligned? Of course, what do you take me for? :) > I'm sure you know alloc() Do you mean alloca? It has a lot of problems, and is generally prohibited at Google. > and malloc() is fast for small sizes. Not nearly fast enough for my purposes.

> Just making sure. Fix that code will you! :) > Yes, alloca. (Don't use it.) > Just make a fast allocator that uses heap instead of the stack. You only need to malloc once and it can be used for any type since like you pointed out, it's effective type can be changed.

Sometimes, especially in embedded systems, it is useful to have a bunch of statically allocated heaps. You can see them in a memory map, and the linker will tell you if they don't fit in memory.

There is also the case where you have some raw data from a file or network, that you want to re-interpret as a struct. That is always dangerous with endianness and struct padding, but it is a very common practice. You could always memcpy from a char array to a struct, but that can waste memory.

Re: The Strict Aliasing Situation Is Pretty Bad

#35
post #30

Although I have no evidence that it is being miscompiled, OpenSSL’s AES implementation uses chunking and is undefined. Oh, that's nice. :/

It's nonsense. The function is external, called from a separately compiled file. The pointer comes in as a char *. The code checks its alignment before assuming it can be cast to a block. There is no way in it could be "miscompiled".

The ivec argument could in fact have come from an object that is of type aes_block_t. The only thing which might reveal that it didn't is wrong alignment. In other regards, there is no way to tell.

Lastly, any cross-compilation-unit optimization which could break code of this type is forbidden, because ISO C says that semantic analysis ends in translation phase 7.

I'm looking at C99, not the latest, but I think it's the same.

In translation phase 7 (second last), "The resulting tokens are syntactically and semantically analyzed and translated as a translation unit." Note the "semantically analyzed": semantic analysis is where the compiler tries to break your code due to strict aliasing.

In translation phase 8 "All external object and function references are resolved. Library components are linked to satisfy external references to functions and objects not defined in the current translation. All such translator output is collected into a program image which contains information needed for execution in its execution environment."

No mention of any more semantic analysis! So unless somehow the mere resolution of external symbols can somehow break OpenSSL's AES, I don't see how anything can go wrong.

One thing I woudl do in that code, though is to make sure that it doesn't use the original ivec pointer. In the case where "chunking" goes on, it should just cast it to the block type, and put the result of that cast in a local variable. All the ememcpy's, load/store macros would be gone, and the increments by AES_BLOCK_SIZE would just be + 1.

Re: The Strict Aliasing Situation Is Pretty Bad

#36
post #15

Earlier quoted context omitted.

It doesn't seem straightforward to me: you're using words like base and derived that aren't in the C standard.

If we talk in terms of concepts that exist in the C standard, we would say that you can't cast an object to pointer-to-X unless your pointer actually points to an X. The reason your example is illegal is that you are casting to pointer-to-"struct derived", but the thing being pointed to is not actually a "struct derived." The "physical subtyping" pattern works because the C standard says that a pointer to a struct, s…

I'm glad I don't have to understand any of this

Re: The Strict Aliasing Situation Is Pretty Bad

#37
post #22

Earlier quoted context omitted.

I don't see text that justifies your one-way argument, the bit of 6.2.7.1 that we are talking about says "and vice versa".

I'm not making a one-way argument. If the underlying object actually is a Derived, you can freely cast between pointer-to-Base and pointer-to-Derived. That is what "and vice versa" means. But if the object isn't actually a Derived, you can't cast to pointer-to-Derived: Derived derived; Derived *pDerived = &derived; // This is legal because it's equivalent to: // Base *pb = &derived.base; // // ie. there actually is a…

Are you sure about 'illegal' there? Is any compiler going to complain?

All the compilers I have used will cheerfully reference unallocated memory; I thought the behavior was undefined.

Re: The Strict Aliasing Situation Is Pretty Bad

#38

Earlier quoted context omitted.

Did you even make sure the memory was aligned? Non-allocated memory (stack char) cannot be used like that. I'm sure you know alloc(), and malloc() is fast for small sizes.

> Did you even make sure the memory was aligned? Of course, what do you take me for? :) > I'm sure you know alloc() Do you mean alloca? It has a lot of problems, and is generally prohibited at Google. > and malloc() is fast for small sizes. Not nearly fast enough for my purposes.

Ok, what's wrong with alloca? Other than blowing the stack, that is.

Re: The Strict Aliasing Situation Is Pretty Bad

#39
post #30

Although I have no evidence that it is being miscompiled, OpenSSL’s AES implementation uses chunking and is undefined. Oh, that's nice. :/

It's nonsense. The function is external, called from a separately compiled file. The pointer comes in as a char *. The code checks its alignment before assuming it can be cast to a block. There is no way in it could be "miscompiled". The ivec argument could in fact have come from an object that is of type aes_block_t. The only thing which might reveal that it didn't is wrong alignment. In other regards, there is no w…

Translation phases are all fun and games, but WPO can still break your code thanks to as-if rules - and because nothing prevent alias analysis to be performed regardless of the TU boundaries. And compilers are doing it.

Re: The Strict Aliasing Situation Is Pretty Bad

#40

Earlier quoted context omitted.

It's nonsense. The function is external, called from a separately compiled file. The pointer comes in as a char *. The code checks its alignment before assuming it can be cast to a block. There is no way in it could be "miscompiled". The ivec argument could in fact have come from an object that is of type aes_block_t. The only thing which might reveal that it didn't is wrong alignment. In other regards, there is no w…

Translation phases are all fun and games, but WPO can still break your code thanks to as-if rules - and because nothing prevent alias analysis to be performed regardless of the TU boundaries. And compilers are doing it.

> nothing prevent alias analysis to be performed regardless of the TU boundaries

Standard conformance does. You know, that principle in the name of which the alias-breaking optimizations are done in the first place.

The "as if" principle (there is only one) means that optimized code produces the same results as the abstract semantics (under a certain set of requirements of what it means for the abstract and actual semantics to agree).

The separation between translation phase 7 and 8 is part of that abstract language semantics.

> And compilers are doing it.

GCC currently only does optimizations across translation unit boundaries when it is told via special options, and only for the .o files which are designated as participating in it. This is no different from using __attribute___ or __asm__.

Post reply on HN