linux - clang memory sanitizer (linux) 不报错

标签 linux clang libc++ sanitizer msan

我试图在 linux 平台上使用玩具程序产生 clang 内存清理器错误。我认为正确的平台/编译/执行没有产生任何错误。

平台的简单描述:

  • docker 容器中的 debian 8
  • 标准 clang 包 (3.5)
  • 使用 these instructions 编译的自定义 (msan) libc++/libc++abi

问题是简单的测试程序不报错。这是测试程序:

#include <iostream>
#include <string>

int main()
{
    auto s = std::string("asdf");
    if (s[5] == 'z')
        std::cout << "asdf\n";
    else
        std::cout << "qwer\n";
    return 0;
}

其中,未初始化的内存被读取。这是它的编译方式:

user@29a0fe911f05:/tmp$ clang++ -v -Wl,-rpath=/tmp/libcxx_msan/lib/ -I /tmp/libcxx_msan/include/ -I /tmp/libcxx_msan/include/c++/v1 -std=c++11 -stdlib=libc++ -fsanitize=memory test.cc
Debian clang version 3.5.0-10 (tags/RELEASE_350/final) (based on LLVM 3.5.0)
Target: x86_64-pc-linux-gnu
Thread model: posix
Found candidate GCC installation: /usr/bin/../lib/gcc/x86_64-linux-gnu/4.8
Found candidate GCC installation: /usr/bin/../lib/gcc/x86_64-linux-gnu/4.8.4
Found candidate GCC installation: /usr/bin/../lib/gcc/x86_64-linux-gnu/4.9
Found candidate GCC installation: /usr/bin/../lib/gcc/x86_64-linux-gnu/4.9.2
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/4.8
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/4.8.4
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/4.9
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/4.9.2
Selected GCC installation: /usr/bin/../lib/gcc/x86_64-linux-gnu/4.9
Candidate multilib: .;@m64
Selected multilib: .;@m64
 "/usr/lib/llvm-3.5/bin/clang" -cc1 -triple x86_64-pc-linux-gnu -emit-obj -mrelax-all -disable-free -disable-llvm-verifier -main-file-name test.cc -mrelocation-model pic -pic-level 2 -pie-level 2 -mdisable-fp-elim -fmath-errno -masm-verbose -mconstructor-aliases -munwind-tables -fuse-init-array -target-cpu x86-64 -target-linker-version 2.25 -v -dwarf-column-info -resource-dir /usr/lib/llvm-3.5/bin/../lib/clang/3.5.0 -I /tmp/libcxx_msan/include/ -I /tmp/libcxx_msan/include/c++/v1 -internal-isystem /usr/include/c++/v1 -internal-isystem /usr/include/clang/3.5.0/include/ -internal-isystem /usr/local/include -internal-isystem /usr/lib/llvm-3.5/bin/../lib/clang/3.5.0/include -internal-externc-isystem /usr/bin/../lib/gcc/x86_64-linux-gnu/4.9/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -std=c++11 -fdeprecated-macro -fdebug-compilation-dir /tmp -ferror-limit 19 -fmessage-length 239 -fsanitize=memory -fno-assume-sane-operator-new -mstackrealign -fobjc-runtime=gcc -fcxx-exceptions -fexceptions -fdiagnostics-show-option -fcolor-diagnostics -o /tmp/test-548974.o -x c++ test.cc
clang -cc1 version 3.5.0 based upon LLVM 3.5.0 default target x86_64-pc-linux-gnu
ignoring nonexistent directory "/include"
ignoring duplicate directory "/usr/include/clang/3.5.0/include"
#include "..." search starts here:
#include <...> search starts here:
 /tmp/libcxx_msan/include
 /tmp/libcxx_msan/include/c++/v1
 /usr/include/c++/v1  
 /usr/include/clang/3.5.0/include
 /usr/local/include
 /usr/bin/../lib/gcc/x86_64-linux-gnu/4.9/include
 /usr/include/x86_64-linux-gnu
 /usr/include
End of search list.
 "/usr/bin/ld" -whole-archive /usr/lib/llvm-3.5/bin/../lib/clang/3.5.0/lib/linux/libclang_rt.msan-x86_64.a -no-whole-archive -pie --hash-style=both --build-id --eh-frame-hdr -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 -o a.out /usr/bin/../lib/gcc/x86_64-linux-gnu/4.9/../../../x86_64-linux-gnu/Scrt1.o /usr/bin/../lib/gcc/x86_64-linux-gnu/4.9/../../../x86_64-linux-gnu/crti.o /usr/bin/../lib/gcc/x86_64-linux-gnu/4.9/crtbeginS.o -L/usr/bin/../lib/gcc/x86_64-linux-gnu/4.9 -L/usr/bin/../lib/gcc/x86_64-linux-gnu/4.9/../../../x86_64-linux-gnu -L/lib/x86_64-linux-gnu -L/lib/../lib64 -L/usr/lib/x86_64-linux-gnu -L/usr/bin/../lib/gcc/x86_64-linux-gnu/4.9/../../.. -L/usr/lib/llvm-3.5/bin/../lib -L/lib -L/usr/lib -rpath=/tmp/libcxx_msan/lib/ /tmp/test-548974.o -lpthread -lrt -lm -ldl -export-dynamic -lc++ -lm -lgcc_s -lgcc -lc -lgcc_s -lgcc /usr/bin/../lib/gcc/x86_64-linux-gnu/4.9/crtendS.o /usr/bin/../lib/gcc/x86_64-linux-gnu/4.9/../../../x86_64-linux-gnu/crtn.o

该程序使用 libc++/libc++abi 库,这些库是使用平台描述中链接的指令编译的。

user@29a0fe911f05:/tmp$ ldd a.out
        linux-vdso.so.1 (0x00007ffeadbb8000)
        libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f5477040000)
        librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007f5476e38000)
        libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f5476b30000)
        libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f5476928000)
        libc++.so.1 => /tmp/libcxx_msan/lib/libc++.so.1 (0x00007f5476580000)
        libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f5476368000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f5475fb8000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f5479950000)
        libc++abi.so.1 => /tmp/libcxx_msan/lib/../lib/libc++abi.so.1 (0x00007f5475cc0000)

这是程序的输出:

user@29a0fe911f05:/tmp$ ./a.out 
qwer

如果平台配置不正确,我可能会产生 clang 内存清理器误报错误,我知道这是预期的行为。当程序链接到未检测的 libc++/libc++abi 时,会产生预期的误报。

user@29a0fe911f05:/tmp$ clang++ -v -std=c++11 -stdlib=libc++ -fsanitize=memory test.cc
Debian clang version 3.5.0-10 (tags/RELEASE_350/final) (based on LLVM 3.5.0)
Target: x86_64-pc-linux-gnu
Thread model: posix
Found candidate GCC installation: /usr/bin/../lib/gcc/x86_64-linux-gnu/4.8
Found candidate GCC installation: /usr/bin/../lib/gcc/x86_64-linux-gnu/4.8.4
Found candidate GCC installation: /usr/bin/../lib/gcc/x86_64-linux-gnu/4.9
Found candidate GCC installation: /usr/bin/../lib/gcc/x86_64-linux-gnu/4.9.2
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/4.8
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/4.8.4
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/4.9
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/4.9.2
Selected GCC installation: /usr/bin/../lib/gcc/x86_64-linux-gnu/4.9
Candidate multilib: .;@m64
Selected multilib: .;@m64
 "/usr/lib/llvm-3.5/bin/clang" -cc1 -triple x86_64-pc-linux-gnu -emit-obj -mrelax-all -disable-free -disable-llvm-verifier -main-file-name test.cc -mrelocation-model pic -pic-level 2 -pie-level 2 -mdisable-fp-elim -fmath-errno -masm-verbose -mconstructor-aliases -munwind-tables -fuse-init-array -target-cpu x86-64 -target-linker-version 2.25 -v -dwarf-column-info -resource-dir /usr/lib/llvm-3.5/bin/../lib/clang/3.5.0 -internal-isystem /usr/include/c++/v1 -internal-isystem /usr/include/clang/3.5.0/include/ -internal-isystem /usr/local/include -internal-isystem /usr/lib/llvm-3.5/bin/../lib/clang/3.5.0/include -internal-externc-isystem /usr/bin/../lib/gcc/x86_64-linux-gnu/4.9/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -std=c++11 -fdeprecated-macro -fdebug-compilation-dir /tmp -ferror-limit 19 -fmessage-length 239 -fsanitize=memory -fno-assume-sane-operator-new -mstackrealign -fobjc-runtime=gcc -fcxx-exceptions -fexceptions -fdiagnostics-show-option -fcolor-diagnostics -o /tmp/test-9f8b7c.o -x c++ test.cc
clang -cc1 version 3.5.0 based upon LLVM 3.5.0 default target x86_64-pc-linux-gnu
ignoring nonexistent directory "/include"
ignoring duplicate directory "/usr/include/clang/3.5.0/include"
#include "..." search starts here:
#include <...> search starts here:
 /usr/include/c++/v1
 /usr/include/clang/3.5.0/include
 /usr/local/include
 /usr/bin/../lib/gcc/x86_64-linux-gnu/4.9/include
 /usr/include/x86_64-linux-gnu
 /usr/include
End of search list.
 "/usr/bin/ld" -whole-archive /usr/lib/llvm-3.5/bin/../lib/clang/3.5.0/lib/linux/libclang_rt.msan-x86_64.a -no-whole-archive -pie --hash-style=both --build-id --eh-frame-hdr -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 -o a.out /usr/bin/../lib/gcc/x86_64-linux-gnu/4.9/../../../x86_64-linux-gnu/Scrt1.o /usr/bin/../lib/gcc/x86_64-linux-gnu/4.9/../../../x86_64-linux-gnu/crti.o /usr/bin/../lib/gcc/x86_64-linux-gnu/4.9/crtbeginS.o -L/usr/bin/../lib/gcc/x86_64-linux-gnu/4.9 -L/usr/bin/../lib/gcc/x86_64-linux-gnu/4.9/../../../x86_64-linux-gnu -L/lib/x86_64-linux-gnu -L/lib/../lib64 -L/usr/lib/x86_64-linux-gnu -L/usr/bin/../lib/gcc/x86_64-linux-gnu/4.9/../../.. -L/usr/lib/llvm-3.5/bin/../lib -L/lib -L/usr/lib /tmp/test-9f8b7c.o -lpthread -lrt -lm -ldl -export-dynamic -lc++ -lm -lgcc_s -lgcc -lc -lgcc_s -lgcc /usr/bin/../lib/gcc/x86_64-linux-gnu/4.9/crtendS.o /usr/bin/../lib/gcc/x86_64-linux-gnu/4.9/../../../x86_64-linux-gnu/crtn.o
user@29a0fe911f05:/tmp$ ldd a.out
        linux-vdso.so.1 (0x00007ffc09be0000)
        libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f3e6c730000)
        librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007f3e6c528000)
        libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f3e6c220000)
        libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f3e6c018000)
        libc++.so.1 => /usr/lib/x86_64-linux-gnu/libc++.so.1 (0x00007f3e6bd10000)
        libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f3e6baf8000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f3e6b748000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f3e6f048000)
user@29a0fe911f05:/tmp$ ./a.out 
==3014== WARNING: MemorySanitizer: use-of-uninitialized-value
    #0 0x7fcb58194a89 in main (/tmp/a.out+0x94a89)
    #1 0x7fcb56cf1b44 in __libc_start_main /build/glibc-I9DIZl/glibc-2.19/csu/libc-start.c:287
    #2 0x7fcb5819427c in _start (/tmp/a.out+0x9427c)

SUMMARY: MemorySanitizer: use-of-uninitialized-value ??:0 main
Exiting

最佳答案

简答:string 是一个特例。

更长的答案:一般来说,std::string 与三个指针的大小相同。一个指向字符串的开头,一个指向结尾,第三个指向分配空间的结尾。 (开始、结束和容量)。在 libc++ 中,std::string 的实现使用“短字符串优化”,如果字符串的内容很短,则数据存储在 24 字节(对于 x86_64)中指针会采取。这消除了许多字符串的堆分配。

我的理解是内存清理器不知道 std::string 的相关信息,因此看起来那些字节已经被写入 - 即使它们已经超过了字符串数据的末尾.

如果将测试字符串更改为 "abcdefghijklmnopqrstuvwxyz0123456789"(然后尝试访问元素 37),会发生什么情况?

附言清洁剂团队最近向我发送了一个补丁,用于将 ASAN 支持添加到 libc++ 的 string 实现中。我也会询问有关 MSAN 的信息。

关于linux - clang memory sanitizer (linux) 不报错,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33639225/

相关文章:

在 Linux Alpine 下构建 llvm 6

c++ - 无法 typedef std::chrono::microseconds 覆盖其定义以更改其基础类型

linux - Bash 从包含空格的路径中删除文件

c - 在 C 代码中需要一些帮助以进行优化(轮询 + 延迟/ sleep )

linux - 在 linux mint 上安装 clang

templates - 带有函数调用表达式的 `decltype` 何时需要定义函数?

python - python 扩展上的地址 sanitizer

c++ - 如何指定自定义 libc++

linux - g++: 错误:无法识别的命令行选项 ‘--32’ ;你是说 ‘-m32’ 吗?

linux - sh/awk(部分)脚本返回空值但希望它返回一个值