我运行的是OS X 10.8.5;我已经通过自制安装了llvm 3.4 (clang版本3.4 (tags/RELEASE_34/final)),并且我正在构建-fsanitize=address。我可以使用简单的演示程序,但是在构建我们的代码库时,我遇到了几个问题(尽管我真的很想要第1条的答案):
-
第三方库正在生成asan错误,并且asan在第一次出现时终止我的应用程序。我认为会有某种(运行时/编译时)选项告诉asan在发现错误后继续运行。具体来说,我看到的是:
bash-3.2$ ASAN_SYMBOLIZER_PATH=/usr/local/Cellar/llvm34/3.4/lib/llvm-3.4/bin/llvm-symbolizer ./unit_test Start testing of PathTrieTest Config: Using QTest library 4.8.2, Qt 4.8.2 PASS : PathTrieTest::initTestCase() PASS : PathTrieTest::pathTrieNodeTest() ================================================================= ==76647==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x61600019e588 at pc 0x10891ddd3 bp 0x11312ba90 sp 0x11312ba58 WRITE of size 48830 at 0x61600019e588 thread T3 #0 0x10891ddd2 in wrap_readdir_r (/usr/local/lib/llvm-3.4/lib/clang/3.4/lib/darwin/libclang_rt.asan_osx_dynamic.dylib+0x11dd2) #1 0x10ac23571 in QFileSystemIterator::advance(QFileSystemEntry&, QFileSystemMetaData&) (/Volumes/ToolChain/qt-4.8/lib/QtCore.framework/Versions/4/QtCore+0xef571) #2 0x10abd86d3 in QDirIteratorPrivate::advance() (/Volumes/ToolChain/qt-4.8/lib/QtCore.framework/Versions/4/QtCore+0xa46d3) #3 0x10abd7a7f in QDirIteratorPrivate::QDirIteratorPrivate(QFileSystemEntry const&, QStringList const&, QFlags<QDir::Filter>, QFlags<QDirIterator::IteratorFlag>, bool) (/Volumes/ToolChain/qt-4.8/lib/QtCore.framework/Versions/4/QtCore+0xa3a7f) #4 0x10abd8b68 in QDirIterator::QDirIterator(QDir const&, QFlags<QDirIterator::IteratorFlag>) (/Volumes/ToolChain/qt-4.8/lib/QtCore.framework/Versions/4/QtCore+0xa4b68) #5 0x10abd7609 in QDirPrivate::initFileLists(QDir const&) const (/Volumes/ToolChain/qt-4.8/lib/QtCore.framework/Versions/4/QtCore+0xa3609) #6 0x10abd5394 in QDir::count() const (/Volumes/ToolChain/qt-4.8/lib/QtCore.framework/Versions/4/QtCore+0xa1394) #7 0x1084c205d in get_count(QFileInfo&) /Users/stebro/dev_vm/ui/ui/fsinfoprovider.cpp:36 ...
此错误不会导致应用程序在未消毒运行时终止。 当使用-fsanitize=undefined(或-fsanitize=address,undefined)选项时,我无法获得代码链接。我将-fsanitize=undefined行包括在我的编译&链接命令,但我得到链接错误,如:
Undefined symbols for architecture x86_64: "typeinfo for __cxxabiv1::__class_type_info", referenced from: __ubsan::checkDynamicType(void*, void*, unsigned long) in libclang_rt.ubsan_osx.a(ubsan_type_hash.o) isDerivedFromAtOffset(__cxxabiv1::__class_type_info const*, __cxxabiv1::__class_type_info const*, long) in libclang_rt.ubsan_osx.a(ubsan_type_hash.o) findBaseAtOffset(__cxxabiv1::__class_type_info const*, long) in libclang_rt.ubsan_osx.a(ubsan_type_hash.o) "typeinfo for __cxxabiv1::__si_class_type_info", referenced from: isDerivedFromAtOffset(__cxxabiv1::__class_type_info const*, __cxxabiv1::__class_type_info const*, long) in libclang_rt.ubsan_osx.a(ubsan_type_hash.o) findBaseAtOffset(__cxxabiv1::__class_type_info const*, long) in libclang_rt.ubsan_osx.a(ubsan_type_hash.o) "typeinfo for __cxxabiv1::__vmi_class_type_info", referenced from: isDerivedFromAtOffset(__cxxabiv1::__class_type_info const*, __cxxabiv1::__class_type_info const*, long) in libclang_rt.ubsan_osx.a(ubsan_type_hash.o) findBaseAtOffset(__cxxabiv1::__class_type_info const*, long) in libclang_rt.ubsan_osx.a(ubsan_type_hash.o)
我不能得到黑名单工作,和-mllvm -asan-globals=0或-mllvm -asan-stack=0似乎不像我期望的那样工作。例如,后者不会抑制上面#1中列出的错误的生成,并且创建如下所示的黑名单也不会抑制错误:
fun:QDirPrivate::initFileLists fun:get_count fun:*opendir2*
最后,使用这些asan选项生成的可执行文件会导致lldb崩溃。我使用的是XCode 5工具附带的lldb;没有使用homebew llvm包部署的lldb,我不知道如何构建它。这里的构建指令输入链接描述有一个指向你应该使用的源的死链接;直接从SVN存储库中提取源代码,使用:
svn co http://llvm.org/svn/llvm-project/lldb/tags/RELEASE_34/final lldb
导致代码无法编译(请求时提供的错误)。
您可以使用-fsanitize=address -fsanitize-recover=address
标志构建项目,并使用环境变量ASAN_OPTIONS=halt_on_error=0
运行。来源:https://github.com/google/sanitizers/wiki/AddressSanitizer
- 可寻址性错误(尤其是像您提到的OOB写入那样的内存损坏)通常非常严重,值得担心。忽略它们不能撤消它们的影响,并且在跳过堆损坏之后,程序很可能在完全不相关的地方崩溃。你可以尝试在禁用readdir_r检查的情况下构建自己的Clang,但我会尝试在第一个地方修复这个错误。
- 你能在http://code.google.com/p/address-sanitizer上提交一个带有复制步骤的bug吗?
- 黑名单只通过不检测它们来禁用黑名单函数中的可寻址性检查,它们不检查某些帧的堆栈。您的特定检查发生在编译到运行时库的函数拦截器中,因此您甚至不能将其列入黑名单。如果#1中的错误是在某些系统库中,并且无法轻松解决,我们可以考虑添加一个运行时选项来禁用readdir_r检查。
- 还是那句话,我希望你能给我一个bug报告。
顺便说一下——如果你从源代码构建它,我发现了一种方法来解决Qt中的堆溢出问题。我相信这个问题与32位/64位索引节点有关(_DARWIN_FEATURE_64_BIT_INODE
在我出于某种原因构建Qt时没有定义)。