Inknow people are quick to complain about programmers relying on UB here but this really is a long standing disagreement with the gcc folk. They are language lawyers of the worst sort and do not consider security implications being a point of discussion :(
> On two occasions I have been asked, — "Pray, Mr. Babbage, if you put into the machine wrong figures, will the right answers come out?" In one case a member of the Upper, and in the other a member of the Lower, House put this question. I am not able rightly to apprehend the kind of confusion of ideas that could provoke such a question. --Charles Babbage The modern version of this seems to be: "Mr. Babbage, I put the…
“gcc will quietly break nearly half of all the packages that it compiles”
41–50 of 110 posts
Re: “gcc will quietly break nearly half of all the packages that it compiles”
#42Earlier quoted context omitted.
> On two occasions I have been asked, — "Pray, Mr. Babbage, if you put into the machine wrong figures, will the right answers come out?" In one case a member of the Upper, and in the other a member of the Lower, House put this question. I am not able rightly to apprehend the kind of confusion of ideas that could provoke such a question. --Charles Babbage The modern version of this seems to be: "Mr. Babbage, I put the…
I believe the complaint is actually that the compiler makes secure code insecure by removing checks that rely on undefined behavior (which presumably can't be made any other way).
Re: “gcc will quietly break nearly half of all the packages that it compiles”
#43Earlier quoted context omitted.
IMO, it's a little subtler than that. It's not the compiler's fault, it's the language's . Plenty of languages have no undefined behavior that can be written by accident. Go and safe Rust, for instance, have just about no undefined behavior at all, and are both performance-competitive with C. (Go has UB if you cause race conditions, and Rust has UB within `unsafe` blocks analogous to C's UB.) A C compiler, meanwhile,…
Umm wait. Undefined behavior is where the language specification is not 100% precise, and compiler implementations can differ on produced code. Go and Rust only have single implementations. The specification for both are very brief. Are you claiming that a clean box implementation of Go and Rust would always behave identically? I have only one thing to say: I clicked through the Golang spec for 30 seconds and found t…
Re: “gcc will quietly break nearly half of all the packages that it compiles”
#44Inknow people are quick to complain about programmers relying on UB here but this really is a long standing disagreement with the gcc folk. They are language lawyers of the worst sort and do not consider security implications being a point of discussion :(
> On two occasions I have been asked, — "Pray, Mr. Babbage, if you put into the machine wrong figures, will the right answers come out?" In one case a member of the Upper, and in the other a member of the Lower, House put this question. I am not able rightly to apprehend the kind of confusion of ideas that could provoke such a question. --Charles Babbage The modern version of this seems to be: "Mr. Babbage, I put the…
Re: “gcc will quietly break nearly half of all the packages that it compiles”
#45Inknow people are quick to complain about programmers relying on UB here but this really is a long standing disagreement with the gcc folk. They are language lawyers of the worst sort and do not consider security implications being a point of discussion :(
> On two occasions I have been asked, — "Pray, Mr. Babbage, if you put into the machine wrong figures, will the right answers come out?" In one case a member of the Upper, and in the other a member of the Lower, House put this question. I am not able rightly to apprehend the kind of confusion of ideas that could provoke such a question. --Charles Babbage The modern version of this seems to be: "Mr. Babbage, I put the…
int *b = &a->something; // pointer arithmetic, doesn't dereference a.
if(a == NULL) return 0;
else something_critical = a->somethingelse;
However, some non-Unix address models that Linux doesn't support don't permit pointer arithmetic on NULL pointers. So the ANSI C standards committee declared it undefined. Which means that gcc can - and eventually did - eliminate the NULL pointer check. This has resulted in privilege escalation vulnerabilities in Linux that didn't exist until gcc decided to optimise the code, some of them quite well-hidden.Re: “gcc will quietly break nearly half of all the packages that it compiles”
#46Earlier quoted context omitted.
IMO, it's a little subtler than that. It's not the compiler's fault, it's the language's . Plenty of languages have no undefined behavior that can be written by accident. Go and safe Rust, for instance, have just about no undefined behavior at all, and are both performance-competitive with C. (Go has UB if you cause race conditions, and Rust has UB within `unsafe` blocks analogous to C's UB.) A C compiler, meanwhile,…
Umm wait. Undefined behavior is where the language specification is not 100% precise, and compiler implementations can differ on produced code. Go and Rust only have single implementations. The specification for both are very brief. Are you claiming that a clean box implementation of Go and Rust would always behave identically? I have only one thing to say: I clicked through the Golang spec for 30 seconds and found t…
Unspecified behaviour is usually intentional ambiguity either to give wiggle room for an optimizer, or to accommodate platform variance. Writing a program with that invokes unspecified behaviour isn't normally a problem, as long as you're not relying on a specific result. Order of argument evaluation is a common example.
Relying on undefined behaviour is almost always bad, and almost always avoidable. That's where the nasal demons come from. Dereferencing null, alias-creating pointer typecasting, etc.
Re: “gcc will quietly break nearly half of all the packages that it compiles”
#47Earlier quoted context omitted.
There's a parable where a man goes to the doctor and says, "Doctor, whenever I drink my coffee with the spoon in the cup, the spoon handle pokes me in the eye and it hurts." And the doctor says, "Well, stop doing that." If you wrote `foo(bar(), baz())` and `baz()` relies on state mutated by `bar()`, your code is bad, and you should feel bad, because experiencing those bad feelings is the way you learn to not write ba…
If bar() returned the mutated state, he could just do: foo(baz(bar()))
This is, of course, a rule of thumb, not a hard law. Some exceptions:
1. I think it's okay (and in fact, idiomatic in C) to mutate state and return some sort of information about what occurred (i.e. a success flag, a number of characters written, etc.).
2. Isolated mutations such as logging sometimes make sense in an otherwise pure function.
Re: “gcc will quietly break nearly half of all the packages that it compiles”
#48Earlier quoted context omitted.
> On two occasions I have been asked, — "Pray, Mr. Babbage, if you put into the machine wrong figures, will the right answers come out?" In one case a member of the Upper, and in the other a member of the Lower, House put this question. I am not able rightly to apprehend the kind of confusion of ideas that could provoke such a question. --Charles Babbage The modern version of this seems to be: "Mr. Babbage, I put the…
Compilers will do things like remove a memset clearing a chunk of memory to zero (because it detects that the variable isn't read again). That sort of thing is bad for security.
Re: “gcc will quietly break nearly half of all the packages that it compiles”
#49Earlier quoted context omitted.
There's a parable where a man goes to the doctor and says, "Doctor, whenever I drink my coffee with the spoon in the cup, the spoon handle pokes me in the eye and it hurts." And the doctor says, "Well, stop doing that." If you wrote `foo(bar(), baz())` and `baz()` relies on state mutated by `bar()`, your code is bad, and you should feel bad, because experiencing those bad feelings is the way you learn to not write ba…
Uhh... The question was "what's an example of undefined behaviour". I gave one, specifically of an example that could realistically break by relying on undefined behaviour. That's it. Simple education. In the context of this post I think that's a good thing because not everyone will understand the topic. You, however, seen to have read some sort of agenda in the question, which I find a little baffling...
Certain things are unspecified. It can call in any order for example.
Other things are undefined. If you do them your program is no longer valid at all, and can crash or corrupt.
Re: “gcc will quietly break nearly half of all the packages that it compiles”
#50The only reasonable thing to say about this was already said upthread of the page, and quoted here: > I have worked on many programs, and whenever I found such a problem (typically called a "portability problem"), where the code was assuming something that the language did not guarantee, I fixed the program rather than bitching about the compiler.
IMO, it's a little subtler than that. It's not the compiler's fault, it's the language's . Plenty of languages have no undefined behavior that can be written by accident. Go and safe Rust, for instance, have just about no undefined behavior at all, and are both performance-competitive with C. (Go has UB if you cause race conditions, and Rust has UB within `unsafe` blocks analogous to C's UB.) A C compiler, meanwhile,…
The real problem here is competition. Gcc is in a competition with clang to produce fast code which makes the gcc developers feel justified when they exploit undefined behaviours for marginal optimizations.
This is a case of following the letter of the law (in this case the C standard) while disregarding its spirit: all the undefined behaviour was so that C compilers could accomodate for odd architectures while remaining close to the metal, not so that compiler programmers could go out of their way to turn their compiler into a mine field.