bool addSigned(int a) { return a + 10 > a; }
bool addUnsigned(unsigned int a) { return a + 10 > a; }
int main() {
// UB reported only with -fsanitize=undefined:
bool res1 = addSigned (0x7ffffffe);
// UB reported only with -fsanitize=unsigned-integer-overflow:
bool res2 = addUnsigned(0xfffffffe);
}
Why? I'd expect res1 to trigger UB report under both fsanitize=undefined/unsigned-integer-overflow
, and res2 to trigger no UB under either.
What am I missing?
-fsanitize=undefined
traps on res1
because it causes undefined behavior. It doesn't trap on res2
because that does not cause undefined behavior.
According to https://source.android.com/docs/security/test/intsan, the -fsanitize=[[un]signed-]integer-overflow
sanitizers are to enable particular subsets of UBSan functionality. UBSan does contain a mode, which is disabled by default, in which it traps on unsigned integer overflow. Even though that is not undefined behavior, there could still be cases where the programmer wants to avoid having unsigned overflow occur, and this option would help them detect it.
So -fsanitize=unsigned-integer-overflow
enables only that trap. It will trap on all instances of unsigned integer overflow, such as res2
. It will not trap on anything else, such as res1
.
The "undefined behavior" in the error message is misleading. Probably UBSan prefixes all its messages with the string "undefined behavior", even for these obscure modes which detect something that's not actually UB.