[go: up one dir, main page]

|
|
Log in / Subscribe / Register

Comparing GCC and Clang security features

Comparing GCC and Clang security features

Posted Sep 16, 2019 7:10 UTC (Mon) by neilbrown (subscriber, #359)
In reply to: Comparing GCC and Clang security features by ballombe
Parent article: Comparing GCC and Clang security features

> Really compilers should just support the keywords __wrap, __trap, __saturate, __overflow and allow to
> declare each integer type separately

These attributes are attributes of the integer operation, not of the integer itself - a bit like 'volatile' which Linus has ranted about.

Maybe it would be even better to think of them as attributes of the assignment.

a = b + c

traps on overflow.

a @= b+c

wraps if b+c overflowed (the symbol has a wrapping around it)

a #= b + c

saturates on overflow (the remnant of the real value gets hashed out)

if you try (b + c) * x you always get a trap, because overflow is mostly bad.
Of course, you could always do
(_tmp @= b+ c) * x
if you really want to wrap a nested expression.


to post comments

Comparing GCC and Clang security features

Posted Sep 16, 2019 14:56 UTC (Mon) by nybble41 (subscriber, #55106) [Link] (2 responses)

Or rather than defining a bunch of new assignment operators, how about __builtin_wrapv(expr) evaluates expr in a context where signed overflow wraps, and __builtin_trapv(expr) does the same but in a context where signed overflow generates an exception? (For lexically scoped operations only, of course—code in other functions shouldn't be affected even if expr includes a function call.) The effect would be the same as if expr were compiled with the -fwrapv or -ftrapv option, respectively.

Comparing GCC and Clang security features

Posted Sep 16, 2019 17:10 UTC (Mon) by excors (subscriber, #95769) [Link] (1 responses)

I think that would behave very unintuitively, because of integer promotions. In code like "unsigned char x = __builtin_wrapv((unsigned char)0x80 + (unsigned char)0x80);", the '+' operator converts its arguments to int and returns an int, so there is no overflow inside the __builtin_wrapv. The assignment converts it to unsigned char, which may overflow, but that's outside the wrapv and will still have implementation-defined behaviour.

The rules for promotion and conversion mean that arithmetic in C is already pretty confusing, so I'm not sure it's a good idea to make it many times more complex with a whole new set of types or operators or magic evaluation contexts.

(Incidentally it looks like you can change the overflow behaviour at function scope with "#pragma GCC optimize("-ftrapv")" etc, which seems slightly less confusing than trying to change it at expression scope. Except it doesn't detect the overflow if e.g. the function gets inlined and evaluated at compile time, so -ftrapv is not actually useful for security.)

Comparing GCC and Clang security features

Posted Sep 16, 2019 22:04 UTC (Mon) by nybble41 (subscriber, #55106) [Link]

In the "unsigned char" case there is no overflow (technically) because the unsigned conversion is defined to use modulo arithmetic. For "signed char", however, you would put the assignment inside, i.e.:

signed char x, y, z;
__builtin_wrapv(x = y + z);

Comparing GCC and Clang security features

Posted Sep 16, 2019 17:54 UTC (Mon) by rgmoore (✭ supporter ✭, #75) [Link]

Maybe it would be even better to think of them as attributes of the assignment.

This sounds like a million bugs waiting to happen. When I use an integer in a context where an overflow might result in a bug, I want a guarantee that the integer hasn't overflowed. Assigning an overflow type to the integer when you declare it provides that guarantee. Requiring the overflow type to the assignment means you can only guarantee the integer hasn't overflowed by going back and checking every assignment to make sure they're of the correct type.

More generally, when would you ever want the same variable to have different overflow behavior in different assignments? Why, for example, would you ever want to have one assignment saturate and another one wrap? I can't think of an example for when that would be sensible, so giving you the power to do it at the expense of removing the utility of the overflow types in guaranteeing that a given value will behave predictably seems like a terrible mistake.


Copyright © 2026, Eklektix, Inc.
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds