Why doesn't this work

If you compile this with gcc -O2, at least for version 6.3 and 6.4 that I've tested, for some reason it optimizes away setting the variables to 0 and gives you a garbage result from adding up uninitialized stack memory. clang, at least 3.8.1, doesn't do that. gcc -O1 also doesn't do that. Is this a compiler bug or some bullshit rulefaggotry where they've decided to break code because the spec says they can somewhere?

#include #include struct Foo { uint32_t a; uint32_t b; uint32_t c; uint32_t d;} __attribute__((packed));uint16_t foo() { uint32_t sum = 0; Foo f; f.a = 0; f.b = 0; f.c = 0; f.d = 0; for(size_t i = 0; i < sizeof(f) / sizeof(uint16_t); ++i) { sum += ((uint16_t *) &f)[i]; } return sum;}int main() { uint16_t sum = foo(); printf("%u\n", sum); return 0;}

If you're curious as to why I'm looking at this, the pseudocode in RFC 1071 for calculating checksums does this and I've run into several programs at work that are now broken because of gcc fucking it. It's 30 year old code and worked fine until now and it's literally RFC compliant.

Other urls found in this thread:

gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html
mail-archive.com/[email protected]/msg01647.html
lkml.org/lkml/2003/2/26/158
rust-lang.org/en-US/
yarchive.net/comp/linux/gcc_vs_kernel_stability.html
lwn.net/Articles/711013/
lwn.net/Articles/711053/
lwn.net/Articles/655028/
ideone.com/Oe5wuP
muppetlabs.com/~breadbox/software/tiny/teensy.html
filippo.io/linux-syscall-table/
man7.org/linux/man-pages/man2/syscalls.2.html
man7.org/linux/man-pages/man2/syscall.2.html
lwn.net/Articles/604287/
lwn.net/Articles/604515/
lwn.net/Articles/604406/
lwn.net/Articles/615809/
nullprogram.com/blog/2016/09/23/
nullprogram.com/blog/2015/05/15/
stackoverflow.com/q/48731306
twitter.com/SFWRedditVideos

It's just the optimizer fucking up your day. It's probably assuming some undefined behavior can't possibly happen and as a result the assignments are dead code which get eliminated. Probably your cast to uint16_t. Try casting to char * which is guaranteed to be able to alias any type.

The struct is already packed by definition you fucking moron, invoking undefined behaviour using compiler extensions (why are you doing this anyway you subhuman) is part of your mistake. You could've googled this and found the answer in a minute, tops

I don't know why, but gcc 6.4 says
#‘target_mem_ref’ not supported by expression#
5.5 says nothing, but doesn't work either. I'm guessing a bug. I couldn't locate it on the bugtracker but didn't try much.

Packed isn't the reason genius.

Also, try compiling with -fno-strict-aliasing.

gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html

It's derived from something where packing matters, qt. This is a simplified version of a TCP pseudoheader checksum.

To add further, I recommend that everyone disable this strict aliasing horseshit. Just add the flag to your makefiles and forget about it. It's just a moronic optimization based on retarded features of the C standard and everyone will be better off without it. It causes more harm than good.

By doing this we join the ranks of Linus Torvalds:

mail-archive.com/[email protected]/msg01647.html
lkml.org/lkml/2003/2/26/158

unsigned long a;a = 5;*(unsigned short *)&a = 4;


GCC BTFO

I'll probably disable it. The bugs strict aliasing optimization creates are non-obvious and security risks. The code I was fixing broke in a way that rejected every packet, but it could just as easily have accepted every packet allowing session hijacks without anyone having noticed the code's behavior had changed.

Yeah, it's scary as fuck. Compilers simply can't be trusted anymore; one bad move and they start deleting side effects from code like it was nothing. I also force integer overflows to be well-defined two's complement behavior by default because there's no actual reason they shouldn't all work that way in 2018.

I'm not actually sure if the strict aliasing is the cause of your problem but it looks like it to me. Please confirm if it works with the flag when you are able.

Yeah, it works with the flag and the assembly shows it's not eliding the assignments.

There is an actual reason for that. Enforcing well-defined results in case of overflow prevents many optimisations from happening that would break if overflow happened. Don't do that unless you actually need that behavior or you can needlessly hurt performance.

You have only yourself to blame OP.

...

If you want to bitbang, you use assembly, not high level languages.

Personally I think it's good that compilers break code. If they produced code that did what you expected that would be insane.
And who the fuck are you to expect anything. You think there's some kind of standard here? Well there is and it says compiler writers can do whatever and users should stfu.

The C language and the compiler were made by 'shit-for-brains weenix unie "programmers"'. That's why your code doesn't work.

Pointers are supposed to be "hard" because of C and all the bullshit that comes with it. Their problem is trying to learn pointers using a language that can't do pointers correctly. Ctards regurgitate the "what's really going on" and "portable assembly" memes so people wind up believing C bullshit is how computers actually work. The only way to "fix" that problem other than real education is by making a language that sucks more than C and blaming all of its bullshit on the machine. Pointers also do not have to work in a way that conforms to C standards. You won't get a Lisp machine from the C way.

I "blame the tools" because the makers of these tools are the source of the problem. There is such a thing as defective and shitty products. A calculator that makes 00011 equal to 00009 is a defective calculator. AT&T is a phone company that was doing UNIX to make extra money on the side, so they didn't care. The switch statement is more bullshit.

These stupid shit-for-brains weenix unie "programmers" havemanaged to break that mainstay of Western enlightenment andeducation, the dictionary. And I'll bet they excuse theirbehavior by saying, "Well, it's all Greek to me"!I suppose it's only appropriate that the invading hordesscraped the librarian at Alexandria to death with shells.They must have had a premonition that UNIX was coming.

I feel compelled to submit the following piece of C code: switch (x) default: if (prime(x)) case 2: case 3: case 5: case 7: process_prime(x); else case 4: case 6: case 8: case 9: case 10: process_composite(x);This can be found in Harbison and Steele's "C: A ReferenceManual" (page 216 in the second edition). They then remark: This is, frankly, the most bizarre switch statement we have ever seen that still has pretenses to being purposeful.In every other programming language the notion of a casedispatch is supported through some rigidly authoritarianconstruct whose syntax and semantics can be grasped by themost primitive programming chimpanzee. But in C this highlystructured notion becomes a thing of sharp edges and losescrews, sort of the programming language equivalent of acloset full of tangled wire hangers.

And I hacked the renderer code to throw cpp the proper"-DFRAME=%05d" to spit out numbers the way I wantedthem. Why did I want the leading zeros? I don't know, I justthought it was cleaner.So I fired up the animation and let it run for a while(days).Well, the output was quite amusing (or at least it wouldhave been if I didn't need the results for my thesis defensea week later). The object would go down for a few frames,then jump up and go down a little, then go back to where itmaybe should have been, then jump up....After a little headscratching, I realized that the leadingzeros in my frame numbers were causing cpp to treat them asoctal values. How precious.But still, if I say "#define FRAME 00009" then "#ifFRAME==00009" should still fire (or it should at least whineat me). Well, 00009==00009 does trigger, but so does00009==00011.Huh? Well, some C library thinks that the nine in 00009 isn'toctal, so it interprets it as 9 decimal. And 00011 is a fineoctal rep of 9 decimal. So, both "#if FRAME==00009" and"#if FRAME==00011" fired and I applied two translate callsto my object geometry. And(!), it's not that having adecimal digit makes the whole number decimal. The string00019 gets interpreted as 00010 octal plus 9 decimal = 17decimal. Lovely, not.

9 is a perfectly acceptable digit in a formally defined octal system. It has a clear meaning. A 9 on the nth position in the representation adds 9•8ⁿ⁻¹ to the value of the number, same as any other digit.
It means you can represent the same number in multiple ways, but that's nothing new. 00.777… = 01, after all.

The problem wasn't with `bc`, and a C compiler is not a calculator. Your UNIX hater is too stupid to understand octal.

A complete nothing-burger

A poorly constructed switch statement, but solid code nonetheless. Can you actually explain the problem? No? Keep copy-pasting, buddy.

As before. You got completely fucking BTFO in the last thread you copy-pasted this garbage, and you just ignored it to move on.

Can you stop trying to derail and/or derailing every thread? Can you fuck off back to OpenVMS or wherever it is you came from? We're working with technology people actually want to use, it's not something you'd be used to.

if it's UB then it's fucking UB.
if you don't like it, pick a different language.

Correct behavior is far more important. The optimizations you're talking about are of the dangerous, security hole-generating nature:


What's the point of optimizing programs if the code ends up broken? When the first step towards debugging something is disabling optimizations, you know your compiler is doing it wrong.


Just because it's undefined behavior doesn't mean the compiler has to go full retard. In fact, if you supply the flag that makes the compiler define what was previously undefined, you will find that it's much more reasonable. All of a sudden, the compiler starts generating perfectly acceptable working code again.

You are using a language that's full of UB because otherwise it wouldn't be efficient enough when ported to other ass-backwards architectures. Correctness never mattered, only muh fast.

You seem to be under impression that C is a general purpose language. It's not. It's specifically designed to run fast while providing bare minimum high level functionality to warrant using it over assembly. If you want a language that's correct, use ADA or Fortran, but don't complain if you can't do certain things or it can't run quite as fast.

Remember children, write your language standards like the Forth one rather than like C.
C: this is 'undefined behavior' which means gcc devs are permitted to break into your house and rape your daughter and it's your fault, you fucking failure. Bad things happen because of original sin by which I mean nasal demons. The purpose of 'undefined behavior' is to punish bad and sinful people via utterly senseless and stupid 'optimizations' that might theoretically improve code automatically generated by a retard. Nasal demon worshippers pretend that this is where C's speed comes from.
Forth: this is 'system-dependent behavior' which means compilers should document the target architecture appropriate thing that happens. The purpose of 'system dependent behavior' is to help programmers know when their code's behavior might vary from target to target, and when it won't.

I wish this board had IDs, then I could just filter your posts. I mean it's entirely obvious that it's your posts without any IDs, but I'd appreciate the luxury of not reading any of that horseshit.

It is allowed to do so.
If you don't understand this fact and its implications, who is the retard here? :^)

IDs are per-thread. That was my first post in this thread.
C is not fast because of dead code elimination. It's not 'low level, with lots og machine-specific behaviors' so that people can write code in it that compilers ignore the intent of. In a low-level language if I write an assignment I want a fucking assignment to happen. You can use Mercury if you want the order of yout operations to not even matter except for data dependencies (fake dats deoendency in the case of I/O).

just so you know the 0009 stuff doesn't compile now on GCC. It's an obvious error and has nothing to do with octal.
Also not sure how you think that switch statement is "solid".


eh isn't that exactly the same idea.
I'm not seeing how Forth would escape the same fate.

Well, that's just not the case anymore. The code will still be amazingly fast even with no strict aliasing and two's complement integers. That's why I recommend that everyone use those flags by default; less undefined behavior in the language is a good thing.

If, after much profiling, you determine that some function can benefit from those optimizations, you can put it in a separate translation unit and then adapt your makefile to compile it separately without the flags. Easy.

Broken "optimized" code shouldn't be the default.

I can underatand it just fine, moron. That's why I pointed out the solution to OP's problems and to the general problem of "compiler people live in their own idiotic dream world where completely broken code is considered correct because some standard says so". The flags force the compiler to define behavior the standard left undefined.

The compiler could just as easily have made those flags the default while hiding the aggressive optimization options that break stuff behind flags. It chose to generate broken code by default instead. It's imprudent, irresponsible and indefensible.

In C, switch statement is a prettifyed goto, and you should treat it as such. It however comes with ability to compile into computed jump table. That code is a perfectly valid way of using it.

Compiler optimization is by definition restructuring your code and removing unnecessary parts. If you don't want it, you should disable optimization.

I blame the better-written standard for Forth escaping this fate in practice, but there's also
1. Forth isn't a popular intermediate target for other languages that generate lots of dead code because that simplifies their own compilers.
2. It isn't as prestigious to have commits to a Forth project (there's only one good open source Forth and its devs already hate how gcc keeps jerking them around with performance regressions due to thread related) so CS grads who think computers don't have bit-widths don't get brownie points for adding optimizations that will only ever A) do nothing at all, or B) break code but it's OK cause nasal demons. That's why C is fast so deal with it.
3. Some massive faggot didn't make a joke about nasal demons in the Forth community.

It's literally their job to produce a compiler that follows the specs (the standard) to the letter. And there you are, blaming them for doing exactly what they're supposed to be doing, because it stops you from violating the specs.

This is how I can tell you're samefagging.

What I still don't get about this relentless stupidity is where it comes from. You come off like a shill, but nobody's paying you.
One theory: some fag knows C. Knowing C isn't impressive--to the point that it is assumed: if you know anything, you should at least also know C. This fag then, rather than try impress through other knowledge, instead argues that C is actually difficult af.
Another theory: these people are all larpers.

Actually correct theory: you're a faggot autist sperging at everyone who doesn't scold C the way you do.

C language has a standard, and compilers follow the standard. And that's that. If you don't like what compilers do, take it to the C committee or whoeverthefuck, because compiler makers won't do shit for you, not if it would violate C specifications.

Even high nasal demon theory doesn't mandate that gcc devs rape my daughter. It just says they ''can"'. I prefer that they compile my code properly like they did when RMS ran things.

if(prime(x) || x == 2 || x == 3 || x == 5 || x == 7) process_prime(x);else process_composite(x);
Isn't that the exact same.

The idea of undefined behavior is not that it varies between implementations, it's that it's not even part of the language. Writing a program with undefined behavior in it just makes it a semantically invalid program.

It would be reasonable if C compilers generated code that did something reasonable in the face of undefined behavior, but that's not what happens. What they do is pretend that undefined behavior is literally impossible and optimize based on that. The compiler sees something that's undefined behavior, realizes that it's impossible and can't happen and then deletes it based on that. For example, it might optimize away your own check for integer overflow if the integer overflowing is undefined behavior. Then, after that code is gone, they might realize there's no point to the surrounding code and delete them too. And so on, and so forth.

That's why optimizers are regarded with healthy suspicion. They're trying to prove things about your program and optimize based on that. When you give them a general statement of fact like "X can't possibly happen, ever", it's like giving a chimp a machinegun.


Nobody really cares about the specs. Specs don't compile or run code. The standard is just some platonic ideal that doesn't actually exist. GCC introduced a lot of extensions to the language, which are enabled by default. This "GNU C" is actually what a lot of people consider to be the C language, and it actually has a lot of useful features such as the ability to take the address of a label. Microsoft C compilers are in such a sad state it's not even funny. Plan 9 C compilers are also not shy about the fact they're compiling their own little derivative of the C language.

You need to literally and explicitly tell GCC to follow the standard rather than it's own custom C language; other compilers might not even support the standard correctly. Not even GCC fully supports all the standards, as the feature matrixes reveal. So don't come to me talking about how compilers follow the letter of the standard. They couldn't care less. The real reason they like to pretend they care is it allows them to win their little benchmarks competitions at the expense of your code.

nvm I forgot about side effects in the if statement.

OR... OR... You can pass in a bunch of flags and it will kill off much of the optimizer-induced brokeneness. The compiler programmers know they're breaking your shit on purpose, that's why they introduced those flags in the first place.

Undefined behaviour != unspecified behaviour.

Yeah? What's your point?

Undefined behavior is when compiler doesn't do anything specific about the thing you're trying to do. So it can go about it one way or the other, randomly. Having edge cases like that undefined is part of the reason C is fast. And you as a programmer should avoid such edge cases.

why are you in this thread?

The behavior is undefined in the first place because it's impossible to resolve it reasonably. i = i++ + ++i for instance. That's not to mention, writing "reasonab'e" code generators for all those edge cases would bloat the compiler immensely and will never possibly cover 100% of them anyway.

Because I wanted to help people not get fucked by compilers? Do you actually have anything to say or do you just want me to go away? OP's problem is solved anyway, and not thanks to any of you pedantic standards-quoting "hurr its your fault" fucks.

Nobody actually writes code like that. People do write code with pointers aliasing other pointers regardless of types, it's a generally useful concept that gets a lot more use than cramming 5 increments into one sequence point. It's a much simpler problem too and it can be solved by, for example, simply not assuming that multiple pointers to the same address can't alias. They're obviously aliasing each other, the compiler can see that but it ignores that fact because the standards allow it. That's indefensible.

It won't win compiler benchmarks then.

Compiler can't know if it's the same address because to figure it out it would have to run the program it's trying to compile, which besides being idiotic notion is biting firmly into the halting problem, and even then it's not a guarantee that in case A it's aliased and in cases BCDXYZ - not. And doing runtime checks would destroy pointer performance. Smart people design shit like that, they thought of it already. Crack open a fucking math book, nigger.

Also. If you need to alias incompatible types so badly, you can use char * as a middleware. At compile time this shuffling is free, and char is automatically compatible with everything.

But it will prevent security holes from being unknowingly introduced into perfectly good code that used to work but now doesn't because of the shiny new optimizations present in new compiler versions.


How the fuck can it not know that the pointer you cast to another type aliases the original pointer?

unsigned long a;a = 5;*(unsigned short *)&a = 4;

How the fuck can it not know that the newly-created unsigned short * points to a? That's fucking stupid. It's statically verifiable, compilers already keep track of data much more complex than that. You expect me to believe the compiler can't do simple static analysis a human could do just by eyeballing the code? I'd rather believe it's because, as you said, it would "bloat" the compiler with "unelegant" case-specific solutions. You can't solve stuff like the halting problem in the general case with a general algorithm, but it turns out you can get pretty close in the real world.

Whatever you say Mr. "Math Wiz". Everyone should still disable strict aliasing anyway, "nigger". Just like the kernel people do. I seriously doubt you're smarter than Linus Torvalds.


The types are not "incompatible". Every single type out there is a multiple of char by definition. Only packed stuctures can have odd sizes. Why is casting to char * OK but casting to int8_t * is undefined when you dereference the pointer even though CHAR_BIT == 8 in any system that touches the internet? Why can't you cast to multiples of char? Because some standard says only char * can alias other types? That's idiotic. Casting to char * just stops the compiler from assuming the pointers can't alias, precisely because char * is the only exception to the strict aliasing rule. Disabling strict aliasing does that for all types. It significantly improves the language.

Just disable the autistic compiler behavior and start programming in a better version of C that does exactly what you expect it to do instead of playing autistic games with the compiler writers to see who knows the standards best.

That's a trivial scenario. Things more complex than that will quickly exhaust it's ability to keep track of it. Then you'll have a situation where it works half the time and half the time it doesn't, which is worse.

Char * was added as an exception because you javaniggers can't write code that doesn't violates aliasing rules. Also char is not the same as int8_t, just like int is not the same as int64_t. Char is a type that's exactly one machine word, int8_t is a type that's exactly 8 bits. Just because most machines in practice use 8 bit words doesn't mean the distinction should be simply dropped. There are plenty of machines that use 16 bit words, and a number of odd ones that use 10 bit words and somesuch. This isn't about you bitching and moaning that writing proper code is too hard for your brainlet self, it's about the principle that C as a language is not tied to specific hardware with specific quirks.

Also just to be clear. Aliasing rules exist because the shit is wholly dependant on hardware quirks such as endianness. At which point you're jacking off hardware ports and not doing the data processing, so you should be using assembly anyway, not C.

sum += ((uint16_t *) &f)[i]; should be uint16_t tmp;memcpy(&tmp, ((uint16_t *) &f) + i, sizeof(tmp));sum += tmp

GCC developers' decisions aside, you're a fucking moron, as evidenced by the fact that you didn't even bother trying to compile the code you're posting.

Something that works many times is worse than giving up and saying "oh well we just can't solve this generally, let's just pretend it's impossible"? My sides.


The rule sucks and programming is better, easier and safer without it. The restrict keyword is a far better solution to strict aliasing and its optimization problems just by virtue of being opt-in.


God damn you are confused. Char is not a word, it's the smallest addressable amount of memory, which is 8 bits in the vast majority of relevant architectures today. Everything else is literally expressed as multiples of those 8 bit chars. Saying the types are "incompatible" is just plain ignorant.


So what? I seriously doubt this is the case here. Just because some dead architecture from the 80s used retarded shit like 7 bit chars doesn't mean we should still be making concessions because of that architecture in 2018. Nobody gives a single fuck, and if it's not x86_64 or ARM, chances are whatever architectural quirks unique to those platforms are irrelevant to the vast majority of C programmers today.


Yeah you can fuck off with your "principles". Nobody really cares about supporting niche architectures they don't even have hardware for to begin with. This is the real world, not the platonic ISO world with its decades of deliberation.

Unless the OP specifies otherwise, I assume he's targeting x86_64. Should he say otherwise, we'll discuss architecture-specific requirements like alignment and endianness.

If you don't intend on writing portable code, use assembly, dipshit.

Fuck off.

If you intend to write code, don't

...

...

hey the reason i had no input here cause i dont know that much but what that user pointed out i understood, maybe try to be more clear next time

It was, obviously, not a perfectly good code. If it was pefrectly good code then it would have had followed C standard. GCC would not mess things up if you follow C standard.
Your code relied on GCC implementation details and it fucked you over.

>Everyone should still disable strict aliasing anyway, "**". Just like the kernel people do. I seriously doubt you're smarter than Linus Torvalds.
You are acting like people who do something just because Google does it. If something works for one project (Linux kernel) it does not mean that wholly different project would have same benefit. Breaking standards of your chosen language should not be taken lightly because you might end up being dependent on just one compiler.

...

I'm not, but I'm not smarter than the GCC developers either. You can find an intelligent informed believer for almost any opinion.
I agree with you otherwise.

Are you OP? pointed out the code works as expected with aliasing turned off.

Perfectly good code works and makes sense. It's got nothing to do with a piece of paper. The only concern is getting the compiler to generate the code you want. The only reason the compiler failed to do so here is some arbitrary rule that says only char pointers can alias other pointers. We disabled that and it worked.


I referenced and quoted the mail where Linus explains _why_he thinks type-based aliasing is garbage. I read the mail, considered it and decided I agree with him. No strict aliasing really should be the default for all compilers.

It's not just "hurr Linus said it it must be true" he presented good reasons why it is the case.


Are you seriously worried about depending on a GCC flag? GCC, the free software compiler that supports everything under the sun? This is not msvc we're talking about here.

You call this "safe code"? Many a security hole has been exploited due to these unexpected and unauditable optimizations.


So what? You think the "portable" memcpy version or whatever other contortions you have to perform in order to maintain standards compliance are going to somehow be better optimized?

You are free to create your superior C compiler. The whole world is waiting for you to save us.

Kill yourself, dumb cuckchanner.

I don't need to. I'm quite happy with GCC with the stupid-by-design feature turned off, thanks.

OP here. If you want to see how fucked this gets, consider this. Even if you try to communicate to the compiler via union that types at the same memory address actually are at the same memory address so the optimizer should fuck off, if you pass the address between functions in the same translation unit and it inlines the code (which is completely up to the compiler as "inline" is a suggestion) it can still break the code. Try changing the "#if 0" in this code to use a function that gcc will probably inline vs one it's been forced to not inline. Totally different result.

#include #include #include #if 0static uint32_t __attribute__ ((noinline)) calc(uint8_t *data, size_t size) {#elsestatic uint32_t calc(uint8_t *data, size_t size) {#endif uint32_t sum = 0; uint16_t *x = (uint16_t *) data; for(size_t i = 0; i < size / 2; ++i) { sum += x[i]; } return sum;}struct Foo { union { struct { uint32_t a; uint32_t b; uint32_t c; uint32_t d; }; uint8_t u8[16]; };};uint16_t foo() { uint32_t sum = 0; Foo f; f.a = 0; f.b = 0; f.c = 0; f.d = 0; sum = calc(f.u8, sizeof(f)); return sum;}int main() { uint16_t sum = foo(); printf("%u\n", sum);}

Then what the fuck are you doing using C in the first place? This language has literally the opposite design goals. Use the right tool for your job, faggot.

No, not really.
int32_t x, y;//...some other code...if(x>0){ y = (x+10)/4;}
(x+10)/4
(x+10)>>2

C was fine for decades before some faggot language lawyers decided that they could wreck a corner case via an autismal reading of the spec. Rather than what we did in the '90s and just fix the compiler to work around perceived mistakes in the standard then roll the fixes into the standard, they're implementing the mistakes as rigorously as they can. It's wrong and dumb.
That example code is literally 30 years old and only now has become a problem and only on one compiler.

no i am not OP. im just some loser who found this thread. i dont know alot but like i said what he said made sence but your comment i read seemed like it was just someone who had very little to say, so i just thought you didnt know what you were talking about... but i see i was wrong. you should have added more to your comment to explain...sorry

It isn't. You explicitly asked the compiler to -O2.

I'm glad the gcc team doesn't work on the kernel. "We NEED to implement this security hole in IPv6 because it's in the standard!"

The right thing to do is implement the standard security hole and also include a switch that will let the user turn it off.

You obviously work at Microsoft.

get ready... are you ready? are you sure?
rust-lang.org/en-US/

poor b8 tbh

and yet the linux kernel still doesnt compile properly in clang because of all the gcc specific shit he put in there...

That's hardly intended though.

failure to plan is planning to fail

Give me a rundown of this thread.
What do I have to do to my CFLAGS to save my Autism Box™?

I'm glad you don't work on the kernel, either. But thanks for sharing your bad opinions.

-fboku-no-pico

Because it's good and has nice compilers with flags that let you turn off the retarded language defects. Without strict aliasing getting in the way, I can finally use things like uint8_t to safely alias every other type and be sure that it's unsigned, unlike char whosed signedness is implementation-defined.


What? Doesn't that mean the code operates correctly? What's your point?

My experience with compiler overflow behavior involves loops, it assumed a condition was always true due to lack of overflow or something, then deleted it and the surrounding code.


So if you turn on optimizations you should expect the compiler to break your program? You think this is reasonable? How long until security best practices start banning optimization techniques? Some mobile platforms already banned dynamic recompilers. Is this the future? We can't have anything nice because of the autism of compiler writers and their broken standards?


Thak god. GCC and glibc people also break binary compatibility between minor compiler/library versions all the time. If they were kernel developers, nobody would ever upgrade to new kernel versions. Those people simply don't give a single fuck about you or me or any of us. Torvalds also made hilarious comments on the matter. Wish I could find the emails.

GNU and its developers are cancer. The only reason their programs are still widely used is nothing better exists.


Nah.


Holy fuck, just NO. Standards suck, fuck them. Just do your own thing, make it good and make it compatible.


So? Clang will support it eventually. One of their goals is compatibility with GCC. Besides, those are free software compilers. It's not like they're depending on msvc features.


Should probably disable all optimization if you like security. Other than that, -fno-strict-aliasing, especially for software you're writing.

Found them.

yarchive.net/comp/linux/gcc_vs_kernel_stability.html

This is how the GNU faggots treat the goddamn Linux kernel developers. Our problems mean nothing to them.

It's high time that Linux move away from GNU for good.

I agree. "GNU/Linux" retards act as if glibc is some kind of gatekeeper for the kernel system calls. Picture related. It's all lies.

I often talk about scrapping glibc and coming up with a liblinux that provides access to all Linux system calls in the most low-level manner possible, enabling applications to simply target Linux directly with 0 dependencies.

It's not a new idea either:

lwn.net/Articles/711013/
lwn.net/Articles/711053/

lwn.net/Articles/655028/

The only reason a liblinux doesn't exist is apparently nobody stepped up and volunteered to do the work. It is quite possible though; here's a simple Linux-specific program that works without libc:

ideone.com/Oe5wuP

I have a small liblinux library but it's very incomplete and only works on x86_64 and ARM. I won't release it in this state. Anyway, I'll probably be developing these ideas on the kill unix thread (>>870218). Here's some more resources in case anyone else is interested:

muppetlabs.com/~breadbox/software/tiny/teensy.html
filippo.io/linux-syscall-table/
man7.org/linux/man-pages/man2/syscalls.2.html
man7.org/linux/man-pages/man2/syscall.2.html
lwn.net/Articles/604287/
lwn.net/Articles/604515/
lwn.net/Articles/604406/
lwn.net/Articles/615809/
nullprogram.com/blog/2016/09/23/
nullprogram.com/blog/2015/05/15/

You all glow to much.

If you have more recent articles/mails that either support or disprove my ideas, I welcome them.

I don't have time to waist on decade+ threads.
It's 2018 Torvalds would have ditched GCC a long time ago if it was that much of a problem or if they hadn't changed/compromised.

"liblinux instead of libc" to make your code unportable. wtf

Who knows? Maybe they haven't switched because it's the best compiler available right now; clang, the only real alternative, doesn't support the GCC extensions. Maybe the GCC people cleaned up their act. Maybe one day Linus will get pissed off so much he'll make his own compiler and it will become the git of compilers. Or not. I don't know.

All I know is GCC, especially G++, still breaks ABI and they still have ludicrous program-eating optimizations, and glibc is still a major pain in the ass to upgrade to the point distros keep multiple versions because it's easier.

Doesn't seem things have changed. Maybe people just adapted. Just like us, with -fno-strict-aliasing.

Portable software is lowest common denominator software. It supports only the features common to all platforms. Programs come out wrong and aren't really native to any one platform. They feel weird in the hands of users. Graphical programs suffer most from this. Only companies looking to cheapen software development could possibly like this.

Portability is overrated and a relic from the olden Unix days where there were tens of architectures and different commercial Unix vendors, all subtly incompatible with each other. That's the context GNU was born in. Now it's mostly just Linux and a couple dominant hardware architectures. You wouldn't lose much by targeting Linux directly; chances are you were going to use Linux anyway. Take advantage of all the great things Linux has to offer.


If you actually care about those operating systems, go ahead and make specific versions of your programs for those operating systems. Use their system calls and features. Make use of everything they have to offer to make the application as great as possible. Don't stand on top of some lowest common denominator portable runtime just to make things easier for yourself. That's just lazy, and it means you don't actually care enough to make your program a first class citizen of those operating systems.

I cringe hard every time I see some crappy mingw port of some random Unix software. I often have to install an entire mingw/cygwin/msys2 environment just to compile that garbage. It doesn't even link to the correct msvcrt.dll. Only GNU faggots who don't _really_ care about Windows could possibly think these half-assed abominations are acceptable.

Industry targets Linux directly. Almost all advanced networking functionality comes to Linux first and gradually is copied by the BSDs (mainly funded by Apple since they can't use Linux).

Yes. That's exactly how things should be. If industry cares about Linux, then it should make Linux software and improve the Linux kernel. If what Linux has is so good that the BSD/mac OS/Windows people are interested in it, they can come and study the code and implement it themselves for their users.

The GPL gives everyone the freedom to study the software for a reason. Linux programmers shouldn't have to waste time and braincells figuring out a shitty way to support all 3 platforms simultaneously. The same is true for Windows developers or BSD developers. Mac OS developers already think this way and the applications there are better for it.

literal SJW mindset, guys

You're trolling me, right?

What's stopping you from using unsigned char you insufferable faggot?

The point is that you made the compiler produce bloated, sub-optimal code because of a retarded overflow corner case that will never happen in reality.
If your program invokes platform-specific undefined behavior, then yes, of course. If you rely on specific quirks of the platform you're targeting, it is your responsibility to nudge the compiler not to break your brittle kludges.
I believe that's already the case. The most risky optimisations are only enabled starting at -O3 since the consensus is that you don't enable that unless you need every inch of speed and are willing to deal with the fallout. It would actually make sense IMHO to introduce an -Osec optimisation level that would enable every -O2 optimisation except those with a significant risk of widening bugs into exploitable security holes. We already have -Og with a similar reasoning behind it.


Not using, demanding that it should be the default when it goes against the spirit of the language.

Because it's not the correct type, moron. When one wants to access data as if it was an array of octets, the correct type to use is pointer to uint8_t by definition and it's sad that one must go the extra mile and disable strict aliasing for this to work correctly. was created for a reason, and that reason is the regular implementation-specific data types of C had become a problem:


Char, short, int, and long are pretty much deprecated. For the love of god don't write new code using this shit in 2018. Even freestanding environments have access to so fucking use it. OP had the good sense to use these types and wrote perfectly good code but his reward was punishment in the form of some language-lawyering compiler "optimizing" his code.

Also, nobody actually uses unsigned char. That's the kind of garbage that people ask confused stackoverflow questions about. Then after some language lawyer shows up with his standards citations, everybody shares a moment of understanding then goes right back to dealing with all the code, functions and interfaces that have already been written using unqualified char and will never, ever be changed. Nothing can be done about this.


So you're telling me the compiler was turned into a "redditor" because the code it generated works perfectly under all cases? It's a "redditor" compiler because it generates correct but suboptimal code with a few extra instructions? And this is supposed to be bad? It's not bad, it's great. That's the exact kind of effect I was lookging for when I enabled the flag. It should be the default. If after much profiling you find a hot segment of code where you _know_ overflow isn't a problem, you can compile it separately with the flag disabled and reap your speed gains.


You're full of bullshit.


It could just as easily do the safe and sensible thing instead.


Undefined behavior is not platform-specific behavior. It'd be great if it was, because (1) something very specific would happen when you invoke it, and (2) the compiler would have to document exactly what the fuck happens in every supported platform. If that was the case, this thread might not even have existed. Even Wikipedia gets this right:


There's even a simple example of signed overflow being assumed to be an impossible occurrence, the compiler deleting the overflow check and eliminating a conditional function call.


Optimizations shouldn't involve risk calculation. What the hell is up with that? It should be absolutely safe to enable optimizations. Most people do as a matter of course, they want the sanic speed; if they didn't, they'd be writing Javascript.

"Consensus?" Only among compiler people. Having the behavior of your program change under your feet when you increase some arbitrary optimization level is ludicrously stupid, doubly so when it ends up inserting security holes into your program. There shouldn't even be different optimization levels each with some nebulous associated "risk", optimization should just be safe by default and that's it.


This is a great idea. Good luck getting it into GCC.


You're the reason people blame C for security holes.

Yeah, I agree it's fucked. My guess is the compiler gives approximately zero fucks about your union because the function is supposed to take an uint8_t * rather than an actual struct Foo. So it's probably still optimizing based on the assumption that x can't possibly alias data even though you literally cast data to uint16_t * and assigned it to x. It probably deleted x[i] and all surrounding code because dereferencing x invokes undefined behavior and therefore it "can't happen".

Why write int_fast32_t when you can write long?

Does anyone use -fno-strict-aliasing, -fwrapv, -fno-delete-null-pointer-checks, or other flags systemwide on Gentoo? What is the performance like?

long isn't guaranteed to be 32 bit. It's guaranteed to be at least 32 bit.

just saying its pretty ironic

You're invoking undefined behavior by casting to an incompatible type, mask and bitshift instead.

#include #include uint16_t foo() { uint32_t sum = 0; uint32_t f[4] = { 0, 0, 0, 0 }; for(size_t i = 0; i < 4; i++) { sum += f[i] & 0xFFFF; sum += f[i] >> 16; } return sum;}int main() { uint16_t sum = foo(); printf("%u\n", sum); return 0;}

same for int_fast32_t, moron

Not him, but int_fast32_t at least tells you exactly what it is.

It doesn't tell you it's long, though.

Stop the autism and just use any other libc, like Alpine does with musl. The GCC thing is a completely different problem, Linux loves to depend on non standard compiler behavior, so the roots behind that Linus rant are also its curse, they can't move away from GCC since they depend heavily on their non-standard features.
I agree with the sentiment of moving away from GNU though.

I like musl, especially the well-written source code, and think it would be an improvement if everyone used it. I just don't agree with this "kernel interface is libc" thing on principle.

The actual Linux kernel-to-user space interface are the assembly entry points; they're architecture-dependent and programming language-agnostic. They shouldn't be hidden away behind some libc whose maintainers don't even like adding Linux-specific system calls to its own API because of muh Unix compatibility. Also, why C? What about other languages? It's a polyglot world out there; they could easily use JIT compilation to dynamically generate code to perform system calls. Why must they be prevented from doing that just to avoid screwing up glib's global state?

I think this deserves more attention.


That's just the thing. If I ask for the manual pages about the Linux system calls, they give me the glibc pages that document the system call wrappers. It's insane if you ask me. It's about as insane as giving me documentation on systemd when I ask for the init system documentation. Why isn't there a page detailing the requirements Linux imposes on all init systems? I'm accessing the Linux kernel manuals yet it gives me user space manual pages.

These things are for some reason deeply entrenched in Linux. So entrenched, the kernel people apparently assume you're using them. It's kinda hard to move away from GNU when people program on top of glib rather than Linux.

People use GCC, GlibC, and GNU extensions because they actually like these features. If they didn't think it was useful, they would obviously not be using it. Nobody is writing software in the C language without the background knowledge that GNU extensions to the C language are not officially ratified by the ISO C language body.

I don't mind GNU extensions to the language. Actually I think they're extremely useful. I don't really care very much what C standards have to say, I care about what compilers do.

stackoverflow.com/q/48731306

>It can then further prove that i < 300 is always true, and so the loop condition can be optimized away.

Undefined behavior claims yet another unsuspecting victim.