Live data from Hacker News

Undefined Behavior in 2017

blog.regehr.org

61–70 of 120 posts

Re: Undefined Behavior in 2017

#61
post #46

> Loops that Neither Perform I/O nor Terminate > Summary: This UB is probably not a problem in practice (even if it is moderately displeasing to some of us). Since LLVM is mostly based around C/C++ semantics this actually turned out to be a problem for rust, because rust can encode diverging functions in its type system and assume certain code sections to be unreachable. If the compiler then optimizes out code and th…

I think that's a great example of how optimisers have gone off the deep end: no reasonable human programmer would think "I can't figure out if this loop terminates, so let's just leave it out", but that appears to be the default behaviour in this case --- when what should happen when the optimiser "gives up" is that it should just translate the code verbatim.

But the optimizer doesn't give up in this case. It successfully figures out that the loop has no side effect except heating up your processor and eliminates it.

Re: Undefined Behavior in 2017

#62

Why don't compilers have an option to reject UB with an compiler error? Surely the compiler must know when it comes across a piece of source code whose semantic is undefined.

The compiler would reject the following function :

int res(int a, int b) { return a + b; }

since it can be UB, for instance if a + b > INT_MAX.

Re: Undefined Behavior in 2017

#63
post #12

I wish there was a GCC switch that made the optimizer go "This is clearly undefined behaviour. I'll stop this compile right here", as opposed to "This is clearly undefined behaviour. Sweet jackpot, it means I can do whatever the heck I want. Drop those NULL checks below, I've got the golden UDB ticket now"

It's not as easy as it seems.

In C `x + 1` is an undefined behavior if `x` is signed and overflows. Optimizer takes advantage of that for loop optimizations.

Re: Undefined Behavior in 2017

#64

Why don't compilers have an option to reject UB with an compiler error? Surely the compiler must know when it comes across a piece of source code whose semantic is undefined.

The compiler would reject the following function : int res(int a, int b) { return a + b; } since it can be UB, for instance if a + b > INT_MAX.

Then by all means reject it, way better than blowing up in production.

Re: Undefined Behavior in 2017

#65
post #64

Earlier quoted context omitted.

The compiler would reject the following function : int res(int a, int b) { return a + b; } since it can be UB, for instance if a + b > INT_MAX.

Then by all means reject it, way better than blowing up in production.

You just destroyed all C code in the world. At that level of paranoia, you've basically defined a brand new language, and if you're going to do that, why make it C at all?

Smart people with a ton of experience in C have already examined the possibility of defining a C dialect with much less undefined behavior in it. In fact, I believe it's been seriously tried more than once by independent groups. And the result has been the same each time; initial excitement and optimism gives way to total failure. It's simply way too deeply ingrained in the definition of C, backed by all the code in the world written in C. If you want less undefined behavior, your only choice is to leave C.

Re: Undefined Behavior in 2017

#66

Earlier quoted context omitted.

In Rust it's pretty limited. Here is the full list, from the Rustonomicron: Dereferencing null or dangling pointers Reading uninitialized memory Breaking the pointer aliasing rules Producing invalid primitive values: dangling/null references a bool that isn't 0 or 1 an undefined enum discriminant a char outside the ranges [0x0, 0xD7FF] and [0xE000, 0x10FFFF] a non-utf8 str Unwinding into another language Causing a da…

> Note that all of these are inside of unsafe blocks. Besides unsafe blocks, Rust has no undefined behavior, and the compiler will prevent you from doing any of these things. It's true that unsafe is needed to get these problems, but they can also occur outside of unsafe blocks. See an example here: https://gankro.github.io/blah/only-in-rust/#unbound-lifetime... Your own code need not use "unsafe" at all, but the pro…

See also https://doc.rust-lang.org/nomicon/working-with-unsafe.html

> unsafe does more than pollute a whole function: it pollutes a whole module. Generally, the only bullet-proof way to limit the scope of unsafe code is at the module boundary with privacy.

Re: Undefined Behavior in 2017

#67
post #38
post #36

Earlier quoted context omitted.

"Very easy" - well, if you think garbage collection is easy... And yes, if you want to allow manual allocation of objects and setting pointers to arbitrary objects, then your two choices are: 1) garbage collection 2) undefined behavior (use-after-free, double-free, dangling pointers, etc.)

> garbage collection is easy... Garbage collection isn't the only way of writing mostly safe systems programs. ESPOL, NEWP are 10 year older than C. PL/8 was the systems programming language used by IBM for their first RISC mainframe, followed by PL/S. Mesa used at Xerox PARC. Modula-2 used at ETHZ and many 16 bit systems. Object Pascal used to write the first versions of Mac OS and Lisa. Ada and SPARK used by high i…

Well, I don't know about half of these programming languages. However:

- ADA requires garbage collection

- Modula-2 and Object pascal have manual memory management, i.e.: "new" and "delete" - together with double-free, use-after-free, and dangling pointers...

I agree that C is by far worse, but please recognize that at least some of the undefined behavior problems are really hard to solve.

EDIT: Oh, and we haven't started talking about multi threading yet, have we?

Re: Undefined Behavior in 2017

#68
post #64

Earlier quoted context omitted.

The compiler would reject the following function : int res(int a, int b) { return a + b; } since it can be UB, for instance if a + b > INT_MAX.

Then by all means reject it, way better than blowing up in production.

I can't tell if this is satirical, but to be clear, you're proposing to disallow addition?

Re: Undefined Behavior in 2017

#69
post #68
post #64

Earlier quoted context omitted.

Then by all means reject it, way better than blowing up in production.

I can't tell if this is satirical, but to be clear, you're proposing to disallow addition?

Rather define the behaviour of what happens when addition of two ints exceed the maximum allowed value.

Re: Undefined Behavior in 2017

#70
post #36
post #17

Earlier quoted context omitted.

It is very easy to be efficiently determined at compile time, other systems programming languages do it, by not having UB on their language standard to start with. If people prefer "performance trumps correctness" and "winning compiler benchmarks is what counts" then they should happily keep getting exploited.

"Very easy" - well, if you think garbage collection is easy... And yes, if you want to allow manual allocation of objects and setting pointers to arbitrary objects, then your two choices are: 1) garbage collection 2) undefined behavior (use-after-free, double-free, dangling pointers, etc.)

Or RAII, a la Rust
Post reply on HN