【问题标题】:Logging control, for Address Sanitizer PLUS Undefined Behavior Sanitizer?日志控制,用于 Address Sanitizer PLUS Undefined Behavior Sanitizer?
【发布时间】:2020-07-01 14:51:02
【问题描述】:

几种消毒剂(来自 GCC 或 Clang)不能组合 - 即在同一构建中同时使用,但 Asan 和 Ubsan 是可组合的 - 即我可以使用“-fsanitize=address,undefined -fsanitize-recover=”构建all ...”,并有一个执行两个消毒剂检查的 exe。到目前为止一切顺利。

生成的可执行文件的 LOGGING 似乎有问题。

在所有情况下,如果未在选项中设置“log_path”,则所有缺陷都会在 stderr 上报告。到目前为止还可以。但是尝试使用 log_path,事情变得很奇怪:

  • 对于仅使用 Asan 构建的 exe,并将 ASAN_OPTIONS 设置为包含“log_path=./ASAN”,Address Saniitizer 缺陷将进入名为 ASAN 的文件中。
  • 对于仅使用 Ubsan 构建的 exe,并将 UBSAN_OPTIONS 设置为包含“log_path=./UBSAN”,未定义行为缺陷将进入名为 UBSAN 的文件中。
  • 对于使用 Asan 和 Ubsan 构建的 exe o Asan 输出到指定的日志文件,但 ubsan 输出只到 stderr o 即使 log_path 仅通过 UBSAN_OPTIONS 设置,并且 ASAN_OPTIONS 未设置,上述情况也适用 o 如果在 ASAN_OPTIONS 和 UBSAN_OPTIONS 中都设置了 log_path,则使用的 log_path 是 UBSAN 的,但只包含 ASAN 结果

是否有一些隐藏的魔法可以让两个消毒剂写入同一个缺陷日志?


要重现,请使用每个消毒剂都有缺陷的简单测试用例:

char *hello = "hello";

int main (int argc, char *argv[])
{
   int x = 1;
   x <<= 32; // Error: (1 << 32) can't be represented in a (32-bit) int
   char some_char = hello [argc *10];
}

构建并运行:(此处使用 g++ 7.3.0,但其他 GCC 版本以及 clang 7.1.0 也显示出相同的基本行为)

仅 Asan - 按预期工作

g++ foo.C -fsanitize=address -fsanitize-recover=all -g
setenv ASAN_OPTIONS "log_path=./ASAN:halt_on_error=0:handle_abort=1:exitcode=0"
a.out 

文件 ASAN。 29648 包含以

开头的缺陷

==29648==ERROR: AddressSanitizer: global-buffer-overflow on address 0x000000400aca at pc 0x0000004009a5 bp 0x7ffffffffe090 sp 0x7ffffffffe088

在 0x000000400aca 线程 T0 处读取大小为 1 主 /tmp/foo.C:7 中的 0x4009a4

仅 Ubsan - 按预期工作

g++ foo.C -fsanitize=undefined -fsanitize-recover=all -g
setenv UBSAN_OPTIONS "log_path=./UBSAN:halt_on_error=0:handle_abort=1:exitcode=0”
a.out

文件 UBSAN.29675 包含

foo.C:6:6: 运行时错误:移位指数 32 对于 32 位类型“int”来说太大

Asan PLUS Ubsan - 奇怪的日志记录行为

g++ foo.C -fsanitize=address,undefined -fsanitize-recover=all -g

setenv ASAN_OPTIONS "log_path=./ASAN:halt_on_error=0:handle_abort=1:exitcode=0"
a.out 

ASAN_OPTIONS 被忽略,所有缺陷都报告在 stderr 上。现在尝试设置 UBSAN_OPTIONS:

setenv UBSAN_OPTIONS "log_path=./UBSAN:halt_on_error=0:handle_abort=1:exitcode=0”
a.out

文件 UBSAN.30352 仅包含 Asan 缺陷:

==30352==错误:AddressSanitizer:全局缓冲区溢出地址 0x000000400aca 在 pc 0x0000004009a5 bp 0x7ffffffffe090 sp 0x7ffffffffe088 在 0x000000400aca 线程 T0 处读取大小为 1 主 /tmp/foo.C:7 中的 0x4009a4

Ubsan 缺陷只写入标准错误:

foo.C:6:6: 运行时错误:移位指数 32 对于 32 位类型“int”来说太大

【问题讨论】:

    标签: address-sanitizer sanitizer ubsan


    【解决方案1】:

    Ubsan 缺陷只写入标准错误:

    这听起来像是一个错误(或者至少是未经测试的设置组合)。

    也就是说,一般来说,ASan 开发人员并不认为 halt_on_error=0 是一个有用的功能 - 您应该在发现错误时修复它们,因为寻找 UB 是毫无意义 你已经溢出缓冲区或使用了悬空内存。 任何事情在那之后都可能发生。

    因此,如果您确实针对这种奇怪的日志记录行为提交了错误,我希望该错误不会受到关注。

    【讨论】:

    • 我不相信这与出错后是否继续有任何关系。正如您在示例中看到的那样,UB 发生在缓冲区溢出之前 - 因此在这种情况下,甚至没有在日志中捕获第一个错误 - 它正在丢失到 stderr 而只有 LATER 缓冲区溢出被捕获到日志中。
    【解决方案2】:

    已确认这实际上是一个错误。 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94328 适用

    【讨论】:

      【解决方案3】:

      我一直在寻找一种将 AddressSantizer 与 avr-gcc 一起使用的方法,其中没有控制台可以检测到运行时代码已崩溃。我仍然需要对其进行试验,但我相信这个用例是该功能没有用处的反例。

      【讨论】:

        猜你喜欢
        • 2022-01-23
        • 2022-08-04
        • 2017-10-09
        • 2021-12-02
        • 2023-04-06
        • 2015-09-17
        • 2018-10-28
        • 1970-01-01
        • 2016-12-25
        相关资源
        最近更新 更多