Как заставить AddressSanitizer не останавливаться после одной ошибки (и других проблем)

Я использую OS X, 10.8.5; Я установил llvm 3.4 через homebrew (clang version 3.4 (tags / 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. Я использую lldb, поставляемый с инструментами XCode 5; lldb не был развернут с пакетом homebew llvm, и я не могу понять, как его собрать. В инструкциях по сборке введите здесь описание ссылки есть неработающая ссылка, указывающая на источник, который вы должны использовать; извлечение исходного кода непосредственно из репозитория svn, используя:

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

    приводит к тому, что код не компилируется (ошибки предоставляются по запросу).


person Steve Broberg    schedule 27.03.2014    source источник
comment
Я нашел способ обойти наблюдаемое вами переполнение кучи Qt. Я разместил это как ответ ниже.   -  person rryan    schedule 07.12.2015


Ответы (3)


Вы можете собрать свой проект с -fsanitize=address -fsanitize-recover=address флагами и запустить с переменной окружения ASAN_OPTIONS=halt_on_error=0. Источник: https://github.com/google/sanitizers/wiki/AddressSanitizer.

person robert    schedule 24.05.2016
comment
Кажется, это новая функция, добавленная после того, как я задал вопрос. Спасибо за обновления. - person Steve Broberg; 07.06.2016
comment
ASAN_OPTIONS не работает в Windows, я пробовал приведенный выше пример, когда я даю ASAN _OPTIONS, он дает unrecognized option. Он отлично работает с ubuntu. - person Jon marsh; 14.10.2019
comment
как работать с переменной окружения ASAN_OPTIONS = halt_on_error = 0 на MAC? - person YuFeng Shen; 11.06.2021

  1. Ошибки адресуемости (особенно повреждения памяти, такие как запись OOB, о которой вы упомянули) обычно достаточно серьезны, чтобы о них беспокоиться. Их игнорирование не может отменить их эффекты, и очень вероятно, что программа выйдет из строя в совершенно несвязанном месте после того, как вы пропустили повреждение кучи. Вы можете попробовать создать свой собственный Clang с отключенными проверками в readdir_r, но я бы попытался исправить ошибку в первую очередь.
  2. Не могли бы вы сообщить об ошибке с инструкциями по воспроизведению на http://code.google.com/p/address-sanitizer?
  3. Черные списки только отключают проверки адресуемости в функциях, занесенных в черный список, не инструментируя их, они не проверяют стеки для определенных кадров. Ваша конкретная проверка происходит в перехватчике функций, скомпилированном в библиотеку времени выполнения, поэтому вы не можете даже занести это в черный список. Если ошибка в №1 находится в какой-то системной библиотеке и ее нелегко обойти, мы можем рассмотреть возможность добавления параметра времени выполнения для отключения проверок readdir_r.
  4. Опять же, мы будем благодарны за отчет об ошибке.
person Glider    schedule 30.04.2014

Кстати, я нашел способ обойти это переполнение кучи в Qt, если вы собираете его из исходников. Я считаю, что проблема связана с 32-битными / 64-битными индексными дескрипторами (_DARWIN_FEATURE_64_BIT_INODE по какой-то причине не определяется, когда я создаю Qt).

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));
person rryan    schedule 07.12.2015
comment
Спасибо. С тех пор мы перешли на Qt5, и проблема, похоже, исчезла. - person Steve Broberg; 07.12.2015