如何使一个错误(和其他问题)后,AddressSanitizer不会停止

时间:2014-03-27 18:22:38

标签: macos clang llvm address-sanitizer

我正在运行OS X,10.8.5;我通过自制软件安装llvm 3.4(clang版本3.4(标签/ RELEASE_34 / final)),我正在使用-fsanitize = address构建。我可以使用简单的演示程序,但在构建我们的代码库时,我遇到了一些问题(虽然我真的只想回答#1):

  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
    ...
    

    此错误不会导致应用程序在未经过无限制运行时终止。

  2. 使用-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)
    
  3. 我无法让黑名单工作,-mllvm -asan-globals = 0或-mllvm -asan-stack = 0似乎没有像我期望的那样工作。例如,后者不会抑制上面#1中列出的错误的产生,并且创建一个类似下面的黑名单也不会抑制错误:

    fun:QDirPrivate::initFileLists
    fun:get_count
    fun:*opendir2*
    
  4. 最后,使用这些asan选项生成的可执行文件会导致lldb崩溃。我正在使用XCode 5工具附带的lldb;没有使用homebew llvm软件包部署lldb,我无法弄清楚如何构建它。构建指令enter link description here有一个死链接,指向您应该使用的源;使用以下命令直接从svn存储库中提取源代码:

    svn co http://llvm.org/svn/llvm-project/lldb/tags/RELEASE_34/final lldb
    

    导致代码无法编译(根据请求提供错误)。

3 个答案:

答案 0 :(得分:14)

您可以使用-fsanitize=address -fsanitize-recover=address标记构建项目,并使用环境变量ASAN_OPTIONS=halt_on_error=0运行。 资料来源:https://github.com/google/sanitizers/wiki/AddressSanitizer

答案 1 :(得分:5)

  1. 可寻址性错误(特别是像你提到的OOB写的内存损坏)通常非常严重,无法担心。忽略它们无法撤消它们的影响,并且在跳过堆损坏之后,程序很可能在完全无关的位置崩溃。 您可以尝试使用readdir_r禁用检查来构建自己的Clang,但我会尝试首先修复错误。
  2. 您能否在http://code.google.com/p/address-sanitizer
  3. 上提交有关复制步骤的错误
  4. 黑名单仅通过不对它们进行检测来禁用黑名单功能中的可寻址性检查,它们不会检查某些帧的堆栈。您的特定检查发生在编译到运行时库中的函数拦截器中,因此您甚至无法将其列入黑名单。如果#1中的错误在某个系统库中并且无法轻松解决,我们可以考虑添加运行时选项以禁用readdir_r检查。
  5. 再次,我们将感谢错误报告。

答案 2 :(得分:1)

顺便说一下 - 如果你是从源代码构建它的话,我找到了解决Qt中这个堆溢出的方法。我认为这个问题与32位/ 64位inode有关(由于某些原因我在构建Qt时没有定义_DARWIN_FEATURE_64_BIT_INODE。)

diff --git a/src/corelib/io/qfilesystemiterator_unix.cpp b/src/corelib/io/qfilesystemiterator_unix.cpp
index 029b989..76b176f 100644
--- a/src/corelib/io/qfilesystemiterator_unix.cpp
+++ b/src/corelib/io/qfilesystemiterator_unix.cpp
@@ -75,6 +75,7 @@ QFileSystemIterator::QFileSystemIterator(const QFileSystemEntry &entry, QDir::Fi
         size_t maxPathName = ::pathconf(nativePath.constData(), _PC_NAME_MAX);
         if (maxPathName == size_t(-1))
             maxPathName = FILENAME_MAX;
+        maxPathName = 99999;
         maxPathName += sizeof(QT_DIRENT) + 1;

         QT_DIRENT *p = reinterpret_cast(::malloc(maxPathName));