混淆整数溢出的 UBSan 结果

Confusing UBSan results for integer overflows

提问人:Ofek Shilon 提问时间:9/28/2022 更新时间:9/28/2022 访问量:309

问:

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); 
}

为什么?我希望 res1 在两者下触发 UB 报告,而 res2 在两者下都不会触发 UB。 我错过了什么?fsanitize=undefined/unsigned-integer-overflow

Godbolt 链接,方便使用

Clang integer-overflow ubsan

评论


答:

2赞 Nate Eldredge 9/28/2022 #1

-fsanitize=undefined陷阱,因为它会导致未定义的行为。它不会陷入困境,因为这不会导致未定义的行为。res1res2

根据 https://source.android.com/docs/security/test/intsan 的说法,消毒剂将启用UBSan功能的特定子集。UBSan 确实包含一种模式,该模式默认处于禁用状态,在该模式下,它会捕获无符号整数溢出。尽管这不是未定义的行为,但在某些情况下,程序员仍希望避免发生未签名的溢出,此选项将帮助他们检测它。-fsanitize=[[un]signed-]integer-overflow

因此,只启用该陷阱。它将捕获所有无符号整数溢出的实例,例如 .它不会困在其他任何东西上,例如.-fsanitize=unsigned-integer-overflowres2res1

错误消息中的“未定义行为”具有误导性。可能 UBSan 在其所有消息前面都带有字符串“undefined behavior”,即使对于这些晦涩难懂的模式,它们检测到实际上不是 UB 的东西。

评论

0赞 Flash Sheridan 3/23/2023
更需要强调的是,当您想要定义的溢出包装行为时才使用无符号,而几乎没有人这样做。我的经验法则是,认为他应该使用无符号的程序员不理解它们。我在 LLVM 代码库中遇到了一个位扭动异常;在多年的静态分析中,我看到了很多程序员的错误,他们认为无符号与非负整数相同。(提示:整数的本质是它有一个新的后继者;无符号是模块化算术的对象。