Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Signed integer overflow is UB in C.


Can't we force the compiler to define the behavior with flags like -fwrapv? I use them as a matter of course. Also use -fno-strict-aliasing.


Yes, you can tell the compiler to generate predictably-behaving output for non-compliant code. However, that code is not valid C anymore, but a dialect.

Since this is a discussion about what C is and is not, I think it's fair to limit ourselves to the actual language as-is.


> that code is not valid C anymore, but a dialect

> I think it's fair to limit ourselves to the actual language as-is

I don't agree. Standard C only ever seems to be discussed when some asinine undefined behavior starts causing problems that we have to work around. No one cares about it otherwise.

It's better to redefine C as whatever the compilers accept. Now we can actually move forward and actually fix problems such as "signed integer overflow is undefined" -- just tell the compilers to start dealing with it.


But they do deal with it -- by assuming it doesn't happen. Wrap or trap don't necessarily change that.

At its heart, behaviour that's undefined like this is a source of optimisation opportunities, because we tend (and especially the preprocessor tends) to write code that assumes it won't happen. C does not lend itself well to iterator patterns that elide the range check entirely, and so it is valuable to the optimiser to be able to assume that a variable that steadily increments will not suddenly turn out to have wrapped. So we may (for example) unroll memory accesses[0], secure in our understanding that when we add 1 three times we will get three consecutive numbers, and (where we would normally add another 1) go ahead and add four at the end of the unrolled loop.

If we trap at that point, the behaviour is different from if we accessed each memory location in turn and trapped when we actually wrapped around. In the C model, the behaviour is still clasically undefined, but we've added a trap to hopefully catch that it happened before running too much further. We still can't assert anything about the state of the program after the trap, to potentially recover from it.

People writing performance-sensitve code get frustrated when a compiler trades performance for safety, so we're probably never going to get "safe" C in that sense. In practice though? This form of undefined behaviour only kicks in at runtime. Make sure your software is bug-free and you need never worry about it.

[0]: Imagine you have a 16 bit signed int that you're using as input into computing an index into an array -- you may know that it's never going to overflow, but how do you tell the compiler?


Compilers are typically benchmarked with ubsan and friends turned off, so when we say "C is fast" [with undefined behavior enabled] and "C is reasonably safe" [with undefined behavior defined] we aren't talking about the same language.


Well, what I really want is a trap on overflow, but since C doesn't support that, modern architectures don't have the capability; you can do it in software (like with ubsan), but you pay a performance penalty.


I mentioned the -fwrapv option to make it wrap around. There's also a -ftrapv option that makes the compiler generate traps.


Most popular C compilers support trapping on integer overflow (i.e. https://gcc.gnu.org/onlinedocs/gcc/Code-Gen-Options.html#ind...), but it does have some overhead as it replaces the native arithmetic instruction with a call to a library function (i.e. https://gcc.gnu.org/onlinedocs/gccint/Integer-library-routin...)




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: