如何使 AddressSanitizer 在出现错误(和其他问题)后不停止

问题描述 投票:0回答:4

我运行的是 OS X,10.8.5;我已经通过自制程序安装了 llvm 3.4(clang 版本 3.4 (tags/RELEASE_34/final) ),并且我正在使用

-fsanitize=address
进行构建。我可以让 asan 使用简单的演示程序,但是在针对我们的代码库进行构建时,我遇到了几个问题(尽管我真的只想回答 #1):

  1. 第 3 方库正在生成 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
...

此错误不会导致应用程序在未经清理的情况下运行时终止。

  1. 使用

    -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)
    
  2. 我无法让黑名单发挥作用,并且

    -mllvm -asan-globals=0
    -mllvm -asan-stack=0
    似乎没有像我预期的那样工作。例如,后者不会抑制上面#1中列出的错误的生成,并且创建如下所示的黑名单也不会抑制错误:

    乐趣:QDirPrivate::initFileLists 乐趣:获取计数 乐趣:opendir2

  3. 最后,使用这些 asan 选项生成的可执行文件会导致 lldb 崩溃。我正在使用 XCode 5 工具附带的 lldb;没有使用 homebew llvm 包部署 lldb,我不知道如何构建它。构建说明在此处输入链接描述有一个死链接,指向您应该使用的源;直接从 svn 存储库中提取源代码,使用:

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

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

macos clang llvm address-sanitizer
4个回答
39
投票

您可以使用

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


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

1
投票

顺便说一句——如果您从源代码构建Qt,我找到了一种解决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
索引 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))
             最大路径名称 = FILENAME_MAX;
+ 最大路径名称 = 99999;
         maxPathName += sizeof(QT_DIRENT) + 1;

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

0
投票

在 Windows 上,您只需设置 ASAN_OPTIONS=continue_on_error=1 ,独特的完整错误报告将与 exit() 时的摘要一起发送到标准输出。无需使用不同的编译器标志进行编译。考虑这篇博客文章

© www.soinside.com 2019 - 2024. All rights reserved.