Live data from Hacker News

Signed Integers Are Two’s Complement

open-std.org

111–120 of 126 posts

Re: Signed Integers Are Two’s Complement

#111

> Naïve overflow checks, which are often security-critical, often get eliminated by compilers. This leads to exploitable code when the intent was clearly not to and the code, while naïve, was correctly performing security checks for two’s complement integers. This is the most critical aspect. We have enough trouble already without the compiler actually fighting against security because this would fail in a machine fr…

Why are you assuming "machine from the 70s"? I know modern processors (DSPs) that need to saturate on integer arithmetic in order to maintain correctness. If you want your naive overflow checks to work on your x86 project, why not just use a compiler option like -fwrapv? IMO, this is just plain ignorance - people arguing against the standard, while believing only their favorite platform is significant. C code is stil…

I've used DSPs and embedded systems, those compilers have sufficient quirks already and usually don't follow the standard to the letter. I'm not worried about "signal" values, I'm worried about pointer arithmetic values.

x86 SIMD is saturating as well

> If you want your naive overflow checks to work on your x86 project, why not just use a compiler option like -fwrapv?

Fair enough. Or people can stop pretending that UB is just an excuse to throw your hands in the air and do whatever they want with the code. Including null checks.

Because when things blow up it's on the major platforms.

Re: Signed Integers Are Two’s Complement

#112
post #58
post #13

Earlier quoted context omitted.

It's undefined for a reason. size_t size = unreasonable large number; char buf = malloc (size); char *mid = buf + size / 2; int index = 0; for (size_t x = 0; x A common optimization by a compiler is to introduce a temporary char *temp = mid + index; prior to the loop and then replace the body of the loop with *(temp++) = x; If the compiler has to worry about integer overflow, this optimization is not valid. (I'm not…

You meant char * buf = malloc(size); You dropped an asterisk. Since changing pointers returned by malloc() is a bad idea, I'd make it: char * const buf = malloc(size);

This is only useful if buf is involved in some preprocessor macrology which perpetrates a hidden mutation of buf.

   BIG_MACRO(x, y, z, buf); // error!
the programmer is informed that, to his or her surprise, BIG_MACRO mutates buf and can take appropriate corrective action.

It's also useful in C++, since innocent-looking function calls can steal mutable references:

   cplusplusfun(x, y, z, buf); // error: arg 4 is non-const ref
No such thing in C, though; function calls are pure pass-by-value.

Changing pointers returned by malloc is sometimes done:

   if ((newptr = realloc(buf, newsize)) != 0)
     buf = newptr;
   else
     ...
In my experience, C code doesn't use const for anywhere near all of the local variables which could be so qualified.

If you enact a coding convention that all unchanged variables must be const, the programmers will just get used to a habit of removing the const whenever they find it convenient to introduce a mutation to a variable. "Oh, crap, error: x wasn't assigned anywhere before so it was const according to our coding convention. Must remove const, recompile; there we go!"

If you want to actually enforce such a convention of adding const, you need help from the compiler: a diagnostic like "foo.c: 123: variable x not mutated; suggest const qualifier".

I've never seen such a diagnostic; do you know of any compiler which has this?

I think that the average C module would spew reams of these diagnostics.

Re: Signed Integers Are Two’s Complement

#113

Earlier quoted context omitted.

>> Even if nobody cares about such a machine, nothing is achieved other than perhaps simplifying a spec. No, I use 16bit values to represent angles in embedded systems all the time. I routinely expect arithmetic on these values to roll over as 2's complement and I expect to take differences of angles using 2's complement all the time. I'm fully aware that this is undefined behavior and needs to be verified on each co…

Yes, it is annoying to rrad comments that assume overflow is always a programming error. You can store the angle as a union of signed and unsigned type. Do arithmetic on the unsigned member, where overflow is defined. (Both members are equivalent angles)

Or you could just convert from the unsigned to the signed type, rather than dragging unions into it.

This conversion doesn't have undefined behavior; it produces an implementation defined result.

C programs can simulate two's complement math using unsigned types, avoiding UB. Then rely on IB to convert between signed and unsigned.

Re: Signed Integers Are Two’s Complement

#114

Earlier quoted context omitted.

Yes, it is annoying to rrad comments that assume overflow is always a programming error. You can store the angle as a union of signed and unsigned type. Do arithmetic on the unsigned member, where overflow is defined. (Both members are equivalent angles)

Not always, but overflows are usually bugs. This is replicated finding of dynamic overflow checking tools, over and over.

And if overflow is well-defined, then those tools must switch your C dialect to a non-ISO-C conforming one in order to do their job.

Re: Signed Integers Are Two’s Complement

#115

Earlier quoted context omitted.

The worst case is that there would not be an ISO C for such machines. As they are very unusual, this does not strike me as a big deal, and definitely less of an issue than making it easier to avoid invoking undefined behavior. I take your point about the possible motives behind this proposal, which seem quite plausible.

But gutting support for sign-magnitude machines has nothing to do with making certain two's complement behaviors defined. It's like saying we have to drop USB 1.0 support in an OS in order to fix missing features in the Bluetooth stack.

I don't think that analogy works well, because if there was a dependency in standards that led to this outcome, would it not be better to break the dependency going forward, or to have avoided it in the first place?

And not having an ISO C standard for sign-magnitude machines (which is not a necessary consequence of the proposed change, it is just the worst case, depending on how ISO chose to deal with the consequences for such machines) does not necessarily force an end to actual C support for them.

Re: Signed Integers Are Two’s Complement

#116

> Naïve overflow checks, which are often security-critical, often get eliminated by compilers. This leads to exploitable code when the intent was clearly not to and the code, while naïve, was correctly performing security checks for two’s complement integers. This is the most critical aspect. We have enough trouble already without the compiler actually fighting against security because this would fail in a machine fr…

By all means, make the change for the new version of the language. In the meantime, though, why are people assuming two's complement?!

Re: Signed Integers Are Two’s Complement

#117
post #65
post #59

Earlier quoted context omitted.

Isn't the quoted part 180 degrees wrong? Such code was not "correctly performing security checks", since it was undefined behaviour - two's complement or not. Which was the whole problem.

Don't leave out the last part: ...was correctly performing security checks for two’s complement integers. More pedantically, they could have written: ...was correctly performing security checks if the standard had been limited to two’s complement integers. But that was clearly the intent.

But the revised version is limited to twos complement and is still undefined, so such a check is still incorrect.

Re: Signed Integers Are Two’s Complement

#118
post #13

Earlier quoted context omitted.

It's undefined for a reason. size_t size = unreasonable large number; char buf = malloc (size); char *mid = buf + size / 2; int index = 0; for (size_t x = 0; x A common optimization by a compiler is to introduce a temporary char *temp = mid + index; prior to the loop and then replace the body of the loop with *(temp++) = x; If the compiler has to worry about integer overflow, this optimization is not valid. (I'm not…

Integer overflow is certainly not undefined for this reason . It's undefined because in the majority of situations, it is the result of a bug, and the actual value (such as a wrapped value) is unexpected and causes a problem. For instance, oh, the Y2038 problem with 32 bit time_t.

>It's undefined because in the majority of situations, it is the result of a bug,

1. If it's a bug, it should overflow or crash (implementation defined, not undefined), or do what Rust does, crash on -o0 (or, if it's illegal to change defined behavior based on optimization level, create a --crash-on-overflow flag) and overflow on everything else.

2. There is plenty of code where it's intentional (such as the infamous if(a+5<a)).

Re: Signed Integers Are Two’s Complement

#119
post #80
post #60

Earlier quoted context omitted.

Yes, there is. Implementation defined means that a conforming implementation _must_ document its behavior. That means that programmers don’t have to use trial and error to figure out how the compiler behaves and don’t have to _hope_ they found all the corner cases.

And that is how we get #if defined(_THIS_THING_SOME_COMPILER_DEFINES) && !defined(__BUT_NOT_THIS_ONE_THAT_COMPILER_X_DEFINES) soup ;)

Better than than silently ignoring an if guard preventing an overflow, and then overflowing anyways on addition.

Re: Signed Integers Are Two’s Complement

#120
have they considered introducing new types for wrapping integers, checked integers and saturating integers. i understand why they might not want to make a change that could have a large effect on existing programs. but if you introduce new types then the new types will only effect new programs that choose to use them and this seems to be something that could be a library change than a language change.
Post reply on HN