Skip to content

[SPIR-V] Heap Use-After-Free in SPIRVEmitIntrinsics.cpp after 8bc8b84225765 commit #111818

@bwlodarcz

Description

@bwlodarcz

Reproducer

Build LLVM with ASAN.
Run:

llc --verify-machineinstrs --spv-emit-nonsemantic-debug-info --spirv-ext=+SPV_KHR_non_semantic_info --print-after=spirv-nonsemantic-debug-info -O0 -mtriple=spirv64-unknown-unknown llvm/test/CodeGen/SPIRV/debug-info/debug-type-pointer.ll -o - 2>&1

What's happening

The memory is freed in method SPIRVEmitIntrinsics::visitAllocaInst(llvm::AllocaInst&) by I.eraseFromParent(); in llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp:1382.
After that accessed in method SPIRVEmitIntrinsics::postprocessTypes() by

   1776   for (auto IB = PostprocessWorklist.rbegin(), IE = PostprocessWorklist.rend();
   1777        IB != IE; ++IB) {
   1778     CallInst *AssignCI = GR->findAssignPtrTypeInstr(*IB);
   1779     Type *KnownTy = GR->findDeducedElementType(*IB);
   1780     if (!KnownTy || !AssignCI || !isa<Instruction>(AssignCI->getArgOperand(0)))
   1781       continue;
   1782     // Try to improve the type deduced after all Functions are processed.
   1783     if (auto *CI = dyn_cast<CallInst>(*IB)) {

The instruction from line 1783 is a culprit.

Summarizing the problem the SmallVector<Instruction *> PostprocessWorklist is storing Instruction * and other methods free them afterwards. In the final iteration the access of the pointers is UAF memory issue for these cases.

Full listing

==3674043==ERROR: AddressSanitizer: heap-use-after-free on address 0x783c3c821be0 at pc 0x5964b098f439 bp 0x7ffd1f724a20 sp 0x7ffd1f724a18
READ of size 1 at 0x783c3c821be0 thread T0
    #0 0x5964b098f438 in llvm::Value::getValueID() const <truncated>llvm-project/llvm/include/llvm/IR/Value.h:533:12
    #1 0x5964b0c87cf0 in llvm::Instruction::getOpcode() const <truncated>llvm-project/llvm/include/llvm/IR/Instruction.h:274:39
    #2 0x5964b0c87bd3 in llvm::CallInst::classof(llvm::Instruction const*) <truncated>llvm-project/llvm/include/llvm/IR/Instructions.h:1557:15
    #3 0x5964b0c87b10 in llvm::isa_impl<llvm::CallInst, llvm::Instruction, void>::doit(llvm::Instruction const&) <truncated>llvm-project/llvm/include/llvm/Support/Casting.h:64:53
    #4 0x5964b0c87ab1 in llvm::isa_impl_cl<llvm::CallInst, llvm::Instruction const*>::doit(llvm::Instruction const*) <truncated>llvm-project/llvm/include/llvm/Support/Casting.h:110:12
    #5 0x5964b0c87841 in llvm::isa_impl_wrap<llvm::CallInst, llvm::Instruction const*, llvm::Instruction const*>::doit(llvm::Instruction const* const&) <truncated>llvm-project/llvm/include/llvm/Support/Casting.h:137:12
    #6 0x5964b0c87776 in llvm::isa_impl_wrap<llvm::CallInst, llvm::Instruction* const, llvm::Instruction const*>::doit(llvm::Instruction* const&) <truncated>llvm-project/llvm/include/llvm/Support/Casting.h:127:12
    #7 0x5964b0c87553 in llvm::CastIsPossible<llvm::CallInst, llvm::Instruction*, void>::isPossible(llvm::Instruction* const&) <truncated>llvm-project/llvm/include/llvm/Support/Casting.h:255:12
    #8 0x5964b0c872f5 in llvm::CastInfo<llvm::CallInst, llvm::Instruction*, void>::doCastIfPossible(llvm::Instruction* const&) <truncated>llvm-project/llvm/include/llvm/Support/Casting.h:493:10
    #9 0x5964b0c86d2c in decltype(auto) llvm::dyn_cast<llvm::CallInst, llvm::Instruction>(llvm::Instruction*) <truncated>llvm-project/llvm/include/llvm/Support/Casting.h:663:10
    #10 0x5964b275bfed in (anonymous namespace)::SPIRVEmitIntrinsics::postprocessTypes() <truncated>llvm-project/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp:1783:20
    #11 0x5964b2753236 in (anonymous namespace)::SPIRVEmitIntrinsics::runOnModule(llvm::Module&) <truncated>llvm-project/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp:1827:14
    #12 0x5964ba1818ed in (anonymous namespace)::MPPassManager::runOnModule(llvm::Module&) <truncated>llvm-project/llvm/lib/IR/LegacyPassManager.cpp:1523:27
    #13 0x5964ba17f787 in llvm::legacy::PassManagerImpl::run(llvm::Module&) <truncated>llvm-project/llvm/lib/IR/LegacyPassManager.cpp:541:44
    #14 0x5964ba1ace05 in llvm::legacy::PassManager::run(llvm::Module&) <truncated>llvm-project/llvm/lib/IR/LegacyPassManager.cpp:1650:14
    #15 0x5964b069ede3 in compileModule(char**, llvm::LLVMContext&) <truncated>llvm-project/llvm/tools/llc/llc.cpp:753:8
    #16 0x5964b069428a in main <truncated>llvm-project/llvm/tools/llc/llc.cpp:412:22
    #17 0x7b8c3d82a1c9 in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16
    #18 0x7b8c3d82a28a in __libc_start_main csu/../csu/libc-start.c:360:3
    #19 0x5964b059dca4 in _start (<truncated>llvm-project/build-debug/bin/llc+0x1b9a8ca4)

0x783c3c821be0 is located 32 bytes inside of 112-byte region [0x783c3c821bc0,0x783c3c821c30)
freed by thread T0 here:
    #0 0x5964b06805ad in operator delete(void*) <truncated>llvm-project/compiler-rt/lib/asan/asan_new_delete.cpp:143:3
    #1 0x5964ba605b05 in llvm::User::operator delete(void*) <truncated>llvm-project/llvm/lib/IR/User.cpp:208:5
    #2 0x5964ba60f670 in llvm::UnaryInstruction::operator delete(void*) <truncated>llvm-project/llvm/include/llvm/IR/InstrTypes.h:70:37
    #3 0x5964ba60c85b in llvm::Value::deleteValue() <truncated>llvm-project/llvm/include/llvm/IR/Instruction.def:171:1
    #4 0x5964b9643600 in llvm::ilist_alloc_traits<llvm::Instruction>::deleteNode(llvm::Instruction*) <truncated>llvm-project/llvm/include/llvm/IR/Instruction.h:1046:6
    #5 0x5964b964348c in llvm::iplist_impl<llvm::simple_ilist<llvm::Instruction, llvm::ilist_iterator_bits<true>, llvm::ilist_parent<llvm::BasicBlock>>, llvm::SymbolTableListTraits<llvm::Instruction, llvm::ilist_iterator_bits<true>, llvm::ilist_parent<llvm::BasicBlock>>>::erase(llvm::ilist_iterator_w_bits<llvm::ilist_detail::node_options<llvm::Instruction, true, false, void, true, llvm::BasicBlock>, false, false>) <truncated>llvm-project/llvm/include/llvm/ADT/ilist.h:205:5
    #6 0x5964b9f764e0 in llvm::Instruction::eraseFromParent() <truncated>llvm-project/llvm/lib/IR/Instruction.cpp:94:37
    #7 0x5964b27f9cd9 in (anonymous namespace)::SPIRVEmitIntrinsics::visitAllocaInst(llvm::AllocaInst&) <truncated>llvm-project/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp:1382:5
    #8 0x5964b27f02b4 in llvm::InstVisitor<(anonymous namespace)::SPIRVEmitIntrinsics, llvm::Instruction*>::visitAlloca(llvm::AllocaInst&) <truncated>llvm-project/llvm/include/llvm/IR/Instruction.def:171:1
    #9 0x5964b2776da4 in llvm::InstVisitor<(anonymous namespace)::SPIRVEmitIntrinsics, llvm::Instruction*>::visit(llvm::Instruction&) <truncated>llvm-project/llvm/include/llvm/IR/Instruction.def:171:1
    #10 0x5964b275a3fc in (anonymous namespace)::SPIRVEmitIntrinsics::runOnFunction(llvm::Function&) <truncated>llvm-project/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp:1737:9
    #11 0x5964b2752a35 in (anonymous namespace)::SPIRVEmitIntrinsics::runOnModule(llvm::Module&) <truncated>llvm-project/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp:1815:16
    #12 0x5964ba1818ed in (anonymous namespace)::MPPassManager::runOnModule(llvm::Module&) <truncated>llvm-project/llvm/lib/IR/LegacyPassManager.cpp:1523:27
    #13 0x5964ba17f787 in llvm::legacy::PassManagerImpl::run(llvm::Module&) <truncated>llvm-project/llvm/lib/IR/LegacyPassManager.cpp:541:44
    #14 0x5964ba1ace05 in llvm::legacy::PassManager::run(llvm::Module&) <truncated>llvm-project/llvm/lib/IR/LegacyPassManager.cpp:1650:14
    #15 0x5964b069ede3 in compileModule(char**, llvm::LLVMContext&) <truncated>llvm-project/llvm/tools/llc/llc.cpp:753:8
    #16 0x5964b069428a in main <truncated>llvm-project/llvm/tools/llc/llc.cpp:412:22
    #17 0x7b8c3d82a1c9 in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16
    #18 0x7b8c3d82a28a in __libc_start_main csu/../csu/libc-start.c:360:3
    #19 0x5964b059dca4 in _start (<truncated>llvm-project/build-debug/bin/llc+0x1b9a8ca4)

previously allocated by thread T0 here:
    #0 0x5964b067fd4d in operator new(unsigned long) <truncated>llvm-project/compiler-rt/lib/asan/asan_new_delete.cpp:86:3
    #1 0x5964ba60350a in llvm::User::allocateFixedOperandUser(unsigned long, unsigned int, unsigned int) <truncated>llvm-project/llvm/lib/IR/User.cpp:145:7
    #2 0x5964ba60350a in llvm::User::operator new(unsigned long, llvm::User::IntrusiveOperandsAllocMarker) <truncated>llvm-project/llvm/lib/IR/User.cpp:161:10
    #3 0x5964b0cb3a90 in llvm::UnaryInstruction::operator new(unsigned long) <truncated>llvm-project/llvm/include/llvm/IR/InstrTypes.h:69:41
    #4 0x5964c607445e in llvm::LLParser::parseAlloc(llvm::Instruction*&, llvm::LLParser::PerFunctionState&) <truncated>llvm-project/llvm/lib/AsmParser/LLParser.cpp:8163:20
    #5 0x5964c605af2f in llvm::LLParser::parseInstruction(llvm::Instruction*&, llvm::BasicBlock*, llvm::LLParser::PerFunctionState&) <truncated>llvm-project/llvm/lib/AsmParser/LLParser.cpp:7050:12
    #6 0x5964c6053bc1 in llvm::LLParser::parseBasicBlock(llvm::LLParser::PerFunctionState&) <truncated>llvm-project/llvm/lib/AsmParser/LLParser.cpp:6701:13
    #7 0x5964c5fbc0d1 in llvm::LLParser::parseFunctionBody(llvm::Function&, unsigned int, llvm::ArrayRef<unsigned int>) <truncated>llvm-project/llvm/lib/AsmParser/LLParser.cpp:6623:9
    #8 0x5964c5fa8b4f in llvm::LLParser::parseDefine() <truncated>llvm-project/llvm/lib/AsmParser/LLParser.cpp:762:10
    #9 0x5964c5f88b2c in llvm::LLParser::parseTopLevelEntities() <truncated>llvm-project/llvm/lib/AsmParser/LLParser.cpp:566:11
    #10 0x5964c5f875c8 in llvm::LLParser::Run(bool, llvm::function_ref<std::optional<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>> (llvm::StringRef, llvm::StringRef)>) <truncated>llvm-project/llvm/lib/AsmParser/LLParser.cpp:94:10
    #11 0x5964c6181208 in parseAssemblyInto(llvm::MemoryBufferRef, llvm::Module*, llvm::ModuleSummaryIndex*, llvm::SMDiagnostic&, llvm::SlotMapping*, bool, llvm::function_ref<std::optional<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>> (llvm::StringRef, llvm::StringRef)>) <truncated>llvm-project/llvm/lib/AsmParser/Parser.cpp:35:8
    #12 0x5964c6180b1d in llvm::parseAssemblyInto(llvm::MemoryBufferRef, llvm::Module*, llvm::ModuleSummaryIndex*, llvm::SMDiagnostic&, llvm::SlotMapping*, llvm::function_ref<std::optional<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>> (llvm::StringRef, llvm::StringRef)>) <truncated>llvm-project/llvm/lib/AsmParser/Parser.cpp:42:10
    #13 0x5964c61816cd in llvm::parseAssembly(llvm::MemoryBufferRef, llvm::SMDiagnostic&, llvm::LLVMContext&, llvm::SlotMapping*, llvm::function_ref<std::optional<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>> (llvm::StringRef, llvm::StringRef)>) <truncated>llvm-project/llvm/lib/AsmParser/Parser.cpp:53:7
    #14 0x5964ba84d6ed in llvm::parseIR(llvm::MemoryBufferRef, llvm::SMDiagnostic&, llvm::LLVMContext&, llvm::ParserCallbacks) <truncated>llvm-project/llvm/lib/IRReader/IRReader.cpp:89:10
    #15 0x5964ba84eb43 in llvm::parseIRFile(llvm::StringRef, llvm::SMDiagnostic&, llvm::LLVMContext&, llvm::ParserCallbacks) <truncated>llvm-project/llvm/lib/IRReader/IRReader.cpp:105:10
    #16 0x5964b0699c3a in compileModule(char**, llvm::LLVMContext&) <truncated>llvm-project/llvm/tools/llc/llc.cpp:571:11
    #17 0x5964b069428a in main <truncated>llvm-project/llvm/tools/llc/llc.cpp:412:22
    #18 0x7b8c3d82a1c9 in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16
    #19 0x7b8c3d82a28a in __libc_start_main csu/../csu/libc-start.c:360:3
    #20 0x5964b059dca4 in _start (<truncated>llvm-project/build-debug/bin/llc+0x1b9a8ca4)

SUMMARY: AddressSanitizer: heap-use-after-free <truncated>llvm-project/llvm/include/llvm/IR/Value.h:533:12 in llvm::Value::getValueID() const
Shadow bytes around the buggy address:
  0x783c3c821900: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fa fa
  0x783c3c821980: fa fa fa fa fa fa fd fd fd fd fd fd fd fd fd fd
  0x783c3c821a00: fd fd fd fd fa fa fa fa fa fa fa fa fd fd fd fd
  0x783c3c821a80: fd fd fd fd fd fd fd fd fd fd fa fa fa fa fa fa
  0x783c3c821b00: fa fa fd fd fd fd fd fd fd fd fd fd fd fd fd fd
=>0x783c3c821b80: fa fa fa fa fa fa fa fa fd fd fd fd[fd]fd fd fd
  0x783c3c821c00: fd fd fd fd fd fd fa fa fa fa fa fa fa fa fd fd
  0x783c3c821c80: fd fd fd fd fd fd fd fd fd fd fd fd fa fa fa fa
  0x783c3c821d00: fa fa fa fa 00 00 00 00 00 00 00 00 00 00 00 00
  0x783c3c821d80: 00 00 fa fa fa fa fa fa fa fa 00 00 00 00 00 00
  0x783c3c821e00: 00 00 00 00 00 00 00 fa fa fa fa fa fa fa fa fa
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
==3674043==ABORTING

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions