llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
29.11k stars 12.01k forks source link

AddressSanitizer: use-after-poison when calling std::memmove() in moveOperands() #61937

Open mattpulver opened 1 year ago

mattpulver commented 1 year ago

Using LLVM 14.0.6 we are experiencing a consistent AddressSanitizer: use-after-poison error w/ stack trace:

==32563==ERROR: AddressSanitizer: use-after-poison on address 0x621001049b60 at pc 0x7fdcbb8b14be bp 0x7fdc88bd2990 sp 0x7fdc88bd2140
READ of size 32 at 0x621001049b60 thread T8
    #0 0x7fdcbb8b14bd in __interceptor_memmove ../../.././libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:810
    #1 0xbc9ed81 in llvm::MachineInstr::addOperand(llvm::MachineFunction&, llvm::MachineOperand const&) [clone .localalias]
    #2 0xbb47ce4 in llvm::InstrEmitter::CreateVirtualRegisters(llvm::SDNode*, llvm::MachineInstrBuilder&, llvm::MCInstrDesc const&, bool, bool, llvm::DenseMap<llvm::SDValue, llvm::Register, llvm::DenseMapInfo<llvm::SDValue, void>, llvm::detail::DenseMapPair<llvm::SDValue, llvm::Register> >&)
    #3 0xbb4e0a9 in llvm::InstrEmitter::EmitMachineNode(llvm::SDNode*, bool, bool, llvm::DenseMap<llvm::SDValue, llvm::Register, llvm::DenseMapInfo<llvm::SDValue, void>, llvm::detail::DenseMapPair<llvm::SDValue, llvm::Register> >&)
    #4 0xbb3972c in llvm::ScheduleDAGSDNodes::EmitSchedule(llvm::MachineInstrBundleIterator<llvm::MachineInstr, false>&)::{lambda(llvm::SDNode*, bool, bool, llvm::DenseMap<llvm::SDValue, llvm::Register, llvm::DenseMapInfo<llvm::SDValue, void>, llvm::detail::DenseMapPair<llvm::SDValue, llvm::Register> >&)#1}::operator()(llvm::SDNode*, bool, bool, llvm::DenseMap<llvm::SDValue, llvm::Register, llvm::DenseMapInfo<llvm::SDValue, void>, llvm::detail::DenseMapPair<llvm::SDValue, llvm::Register> >&) const
    #5 0xbb3f9c4 in llvm::ScheduleDAGSDNodes::EmitSchedule(llvm::MachineInstrBundleIterator<llvm::MachineInstr, false>&)
    #6 0xba7b0f5 in llvm::SelectionDAGISel::CodeGenAndEmitDAG() [clone .localalias]
    #7 0xba7dbef in llvm::SelectionDAGISel::SelectAllBasicBlocks(llvm::Function const&)
    #8 0xba80371 in llvm::SelectionDAGISel::runOnMachineFunction(llvm::MachineFunction&) [clone .part.0]
    #9 0xb11c200 in (anonymous namespace)::X86DAGToDAGISel::runOnMachineFunction(llvm::MachineFunction&)
    #10 0xbc99d66 in llvm::MachineFunctionPass::runOnFunction(llvm::Function&)
    #11 0xd183abf in llvm::FPPassManager::runOnFunction(llvm::Function&)
    #12 0xd183c2b in llvm::FPPassManager::runOnModule(llvm::Module&)
    #13 0xd1853fe in llvm::legacy::PassManagerImpl::run(llvm::Module&)
    #14 0xc820955 in llvm::MCJIT::emitObject(llvm::Module*) [clone .localalias]
    #15 0xc820fe4 in llvm::MCJIT::generateCodeForModule(llvm::Module*)
    #16 0xc81d937 in llvm::MCJIT::finalizeObject() [clone .localalias]
...

0x621001049b60 is located 3680 bytes inside of 4096-byte region [0x621001048d00,0x621001049d00)
allocated by thread T8 here:
    #0 0x7fdcbb927007 in operator new(unsigned long) ../../.././libsanitizer/asan/asan_new_delete.cpp:99
    #1 0x87191ff in llvm::MallocAllocator::Allocate(unsigned long, unsigned long)
    #2 0x87191ff in llvm::BumpPtrAllocatorImpl<llvm::MallocAllocator, 4096ul, 4096ul, 128ul>::StartNewSlab()
    #3 0x87191ff in llvm::BumpPtrAllocatorImpl<llvm::MallocAllocator, 4096ul, 4096ul, 128ul>::Allocate(unsigned long, llvm::Align)
    #4 0xbc98480 in llvm::MachineFunction::init()

...
SUMMARY: AddressSanitizer: use-after-poison ../../.././libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:810 in __interceptor_memmove
Shadow bytes around the buggy address:
  0x0c4280201310: 00 00 00 00 f7 f7 f7 f7 f7 f7 f7 f7 f7 00 00 00
  0x0c4280201320: 00 00 00 00 00 00 f7 f7 f7 f7 f7 f7 f7 f7 f7 00
  0x0c4280201330: 00 00 00 00 00 00 00 00 f7 f7 f7 f7 f7 f7 f7 f7
  0x0c4280201340: f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7
  0x0c4280201350: f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7
=>0x0c4280201360: f7 f7 00 00 00 00 00 00 00 00 00 f7[f7]f7 f7 f7
  0x0c4280201370: f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7
  0x0c4280201380: f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7
  0x0c4280201390: f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7
  0x0c42802013a0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c42802013b0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
...
  Heap left redzone:       fa
  Poisoned by user:        f7

It has been difficult to reduce this to a simple self-contained example, but our question is:

When std::memmove() was added in https://github.com/llvm/llvm-project/commit/5c0e64fcd6d93ed1033165ed74b524831fff285e was the fact that some of the memory may contain llvm-poisoned addresses taken into consideration? (Or possibly the poisoning of such memory after std::memmove() was added?)

That is, https://github.com/llvm/llvm-project/blob/f56b5921d3954cbd99175d0df44030e7782bc456/llvm/lib/CodeGen/MachineInstr.cpp#L187 contains 2 calls to https://github.com/llvm/llvm-project/blob/f56b5921d3954cbd99175d0df44030e7782bc456/llvm/lib/CodeGen/MachineInstr.cpp#L174 which in turn calls std::memmove() which is touching the poisoned memory, but not necessarily using those value, but is sufficient to trigger the use-after-poison ASan error.

OS: CentOS 7 Compiler: GCC 11.1.0

EugeneZelenko commented 1 year ago

Could you please try 16 or main branch?