You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

启用AddressSanitizer时Clang Libtooling示例出现use-after-poison错误求助

问题描述

在使用AddressSanitizer测试Clang Libtooling示例时,遇到了use-after-poison错误。使用预编译版本的clang 14.0.0,相关代码、测试步骤及报错信息如下:

相关文件

CMakeLists.txt

cmake_minimum_required(VERSION 3.10)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

find_package(LLVM  REQUIRED CONFIG)
find_package(Clang REQUIRED CONFIG)
include_directories(SYSTEM "${LLVM_INCLUDE_DIRS};${CLANG_INCLUDE_DIRS}")

if(NOT LLVM_ENABLE_RTTI)
  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti")
endif()

add_executable(test
  test.cpp
)

target_link_libraries(test
  PRIVATE
    clang
    LLVMSupport
    clangAST
    clangASTMatchers
    clangBasic
    clangFrontend
    clangFrontendTool
    clangSerialization
    clangTooling
)

target_link_libraries(test
  PRIVATE
    pthread
    z
    dl
)

target_compile_options(test
  PRIVATE
    -fsanitize=address
)

target_link_options(test
  PRIVATE
    -fsanitize=address
)

test.cpp

#include "clang/AST/ASTConsumer.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/FrontendAction.h"
#include "clang/Tooling/Tooling.h"

using namespace clang;

class FindNamedClassVisitor
  : public RecursiveASTVisitor<FindNamedClassVisitor> {
public:
  explicit FindNamedClassVisitor(ASTContext *Context)
    : Context(Context) {}

  bool VisitCXXRecordDecl(CXXRecordDecl *Declaration) {
    if (Declaration->getQualifiedNameAsString() == "n::m::C") {
      FullSourceLoc FullLocation = Context->getFullLoc(Declaration->getBeginLoc());
      if (FullLocation.isValid())
        llvm::outs() << "Found declaration at "
                     << FullLocation.getSpellingLineNumber() << ":"
                     << FullLocation.getSpellingColumnNumber() << "\n";
    }
    return true;
  }

private:
  ASTContext *Context;
};

class FindNamedClassConsumer : public clang::ASTConsumer {
public:
  explicit FindNamedClassConsumer(ASTContext *Context)
    : Visitor(Context) {}

  virtual void HandleTranslationUnit(clang::ASTContext &Context) {
    Visitor.TraverseDecl(Context.getTranslationUnitDecl());
  }
private:
  FindNamedClassVisitor Visitor;
};

class FindNamedClassAction : public clang::ASTFrontendAction {
public:
  virtual std::unique_ptr<clang::ASTConsumer> CreateASTConsumer(
    clang::CompilerInstance &Compiler, llvm::StringRef InFile) {
    return std::make_unique<FindNamedClassConsumer>(&Compiler.getASTContext());
  }
};

int main(int argc, char **argv) {
  if (argc > 1) {
    clang::tooling::runToolOnCode(std::make_unique<FindNamedClassAction>(), argv[1]);
  }
}

测试命令

mkdir build
cd build
CC=clang CXX=clang++ cmake ..
./test "int main() {}"

AddressSanitizer报错信息

=================================================================
==3172567==ERROR: AddressSanitizer: use-after-poison on address 0x62100000e748 at pc 0x7f09e999258d bp 0x7ffed63716d0 sp 0x7ffed6370e78
WRITE of size 8 at 0x62100000e748 thread T0
    #0 0x7f09e999258c in __interceptor_memcpy ../../../../src/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:790
    #1 0x55c6c20ce86a in clang::Decl::setAttrs(llvm::SmallVector<clang::Attr*, 4u> const&) (/home/tom/slicer/build/test+0x86286a)
    #2 0x55c6c20ce585 in clang::Decl::addAttr(clang::Attr*) (/home/tom/slicer/build/test+0x862585)
    #3 0x55c6c1fcb895 in clang::ASTContext::buildImplicitRecord(llvm::StringRef, clang::TagTypeKind) const (/home/tom/slicer/build/test+0x75f895)
    #4 0x55c6c1fe6973 in clang::ASTContext::getCFConstantStringDecl() const (/home/tom/slicer/build/test+0x77a973)
    #5 0x55c6c2767583 in clang::Sema::Initialize() (/home/tom/slicer/build/test+0xefb583)
    #6 0x55c6c267b4a9 in clang::Parser::Initialize() (/home/tom/slicer/build/test+0xe0f4a9)
    #7 0x55c6c2677b95 in clang::ParseAST(clang::Sema&, bool, bool) (/home/tom/slicer/build/test+0xe0bb95)
    #8 0x55c6c23d9428 in clang::FrontendAction::Execute() (/home/tom/slicer/build/test+0xb6d428)
    #9 0x55c6c24041b5 in clang::CompilerInstance::ExecuteAction(clang::FrontendAction&) (/home/tom/slicer/build/test+0xb981b5)
    #10 0x55c6c267310c in clang::tooling::FrontendActionFactory::runInvocation(std::shared_ptr<clang::CompilerInvocation>, clang::FileManager*, std::shared_ptr<clang::PCHContainerOperations>, clang::DiagnosticConsumer*) (/home/tom/slicer/build/test+0xe0710c)
    #11 0x55c6c2672e69 in clang::tooling::ToolInvocation::runInvocation(char const*, clang::driver::Compilation*, std::shared_ptr<clang::CompilerInvocation>, std::shared_ptr<clang::PCHContainerOperations>) (/home/tom/slicer/build/test+0xe06e69)
    #12 0x55c6c2671e03 in clang::tooling::ToolInvocation::run() (/home/tom/slicer/build/test+0xe05e03)
    #13 0x55c6c267160e in clang::tooling::runToolOnCodeWithArgs(std::unique_ptr<clang::FrontendAction, std::default_delete<clang::FrontendAction> >, llvm::Twine const&, llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem>, std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&, llvm::Twine const&, llvm::Twine const&, std::shared_ptr<clang::PCHContainerOperations>) (/home/tom/slicer/build/test+0xe0560e)
    #14 0x55c6c267126f in clang::tooling::runToolOnCodeWithArgs(std::unique_ptr<clang::FrontendAction, std::default_delete<clang::FrontendAction> >, llvm::Twine const&, std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&, llvm::Twine const&, llvm::Twine const&, std::shared_ptr<clang::PCHContainerOperations>, std::vector<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > > const&) (/home/tom/slicer/build/test+0xe0526f)
    #15 0x55c6c2670f02 in clang::tooling::runToolOnCode(std::unique_ptr<clang::FrontendAction, std::default_delete<clang::FrontendAction> >, llvm::Twine const&, llvm::Twine const&, std::shared_ptr<clang::PCHContainerOperations>) (/home/tom/slicer/build/test+0xe04f02)
    #16 0x55c6c1d7f82f in main (/home/tom/slicer/build/test+0x51382f)
    #17 0x7f09e938c082 in __libc_start_main ../csu/libc-start.c:308
    #18 0x55c6c1d7f58d in _start (/home/tom/slicer/build/test+0x51358d)

0x62100000e748 is located 2632 bytes inside of 4096-byte region [0x62100000dd00,0x62100000ed00)
allocated by thread T0 here:
    #0 0x7f09e9a06587 in operator new(unsigned long) ../../../../src/libsanitizer/asan/asan_new_delete.cc:104
    #1 0x55c6c1d80b54 in llvm::MallocAllocator::Allocate(unsigned long, unsigned long) (/home/tom/slicer/build/test+0x514b54)
    #2 0x55c6c1ddcc3a in llvm::BumpPtrAllocatorImpl<llvm::MallocAllocator, 4096ul, 4096ul, 128ul>::StartNewSlab() (/home/tom/slicer/build/test+0x570c3a)
    #3 0x55c6c1dbd440 in llvm::BumpPtrAllocatorImpl<llvm::MallocAllocator, 4096ul, 4096ul, 128ul>::Allocate(unsigned long, llvm::Align) (/home/tom/slicer/build/test+0x551440)
    #4 0x55c6c20c4b93 in clang::Decl::operator new(unsigned long, clang::ASTContext const&, clang::DeclContext*, unsigned long) (/home/tom/slicer/build/test+0x858b93)
    #5 0xbebebebebebebebd  (<unknown module>)

SUMMARY: AddressSanitizer: use-after-poison ../../../../src/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:790 in __interceptor_memcpy
Shadow bytes around the buggy address:
  0x0c427fff9c90: f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7
  0x0c427fff9ca0: f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 00 00 04
  0x0c427fff9cb0: 00 00 00 00 00 00 00 00 00 00 00 f7 00 00 04 00
  0x0c427fff9cc0: 00 00 00 00 00 00 00 00 00 00 f7 00 00 00 00 00
  0x0c427fff9cd0: 00 00 00 00 00 00 00 00 00 00 00 00 00 f7 f7 f7
=>0x0c427fff9ce0: f7 f7 f7 f7 f7 f7 f7 f7 f7[f7]f7 f7 f7 f7 f7 f7
  0x0c427fff9cf0: f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7
  0x0c427fff9d00: f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7
  0x0c427fff9d10: f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7
  0x0c427fff9d20: f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7
  0x0c427fff9d30: f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07 
  Heap left redzone:       fa
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
  Shadow gap:              cc
==3172567==ABORTING

关闭CMakeLists.txt中的-fsanitize=address标志后程序运行正常,但希望启用该标志以检测Libtooling程序中的内存损坏错误,求解决方法。


解决方案

这个问题的核心原因是:预编译的Clang/LLVM库未启用AddressSanitizer编译,而你的程序启用了ASan,导致LLVM内部的BumpPtrAllocator内存区域被ASan标记为poisoned,但库本身的代码没有处理该标记,从而触发误报。以下是三种可行的解决方式:

方法1:仅对自有代码启用ASan检测

修改CMakeLists.txt,添加ASan黑名单,跳过LLVM/Clang库的内存检测,只检测你自己编写的代码:

  1. 修改target_compile_options配置:
target_compile_options(test
  PRIVATE
    -fsanitize=address
    -fsanitize-blacklist=asan_blacklist.txt
)

target_link_options(test
  PRIVATE
    -fsanitize=address
)
  1. 在项目根目录创建asan_blacklist.txt文件,内容如下:
# 跳过LLVM/Clang相关的函数和类检测
fun:clang::*
fun:llvm::*
class:clang::*
class:llvm::*

这种方式既能保留对自有代码的ASan检测能力,又能避免与预编译LLVM库的冲突。

方法2:自行编译带ASan的LLVM/Clang

如果需要完整检测包括LLVM库在内的所有代码,可从源码编译带ASan的LLVM和Clang:

  1. 克隆对应14.0.0版本的LLVM项目源码
  2. 编译时添加以下CMake参数:
cmake -S llvm -B build \
  -DCMAKE_BUILD_TYPE=Debug \
  -DLLVM_ENABLE_PROJECTS="clang" \
  -DLLVM_USE_SANITIZER=Address \
  -DCMAKE_C_COMPILER=clang \
  -DCMAKE_CXX_COMPILER=clang++
  1. 编译完成后,使用该版本的Clang和库构建你的Libtooling程序,此时ASan可正常工作无冲突。

方法3:临时禁用poisoned内存检测

通过环境变量临时关闭ASan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 23:40:08