Skip to content

[ARM] IselLowering unsigned overflow to crash using APInt in PerformSHLSimplify #59317

@DataCorrupted

Description

@DataCorrupted

When compiling the following code with arm or armeb:

define i1 @f(i16 %F) {
BB:
  %E = extractelement <1 x i16> <i16 -1>, i16 %F
  %RP = alloca i64, align 8
  %B = shl i16 %E, %E
  %C1 = icmp ugt i16 %B, %F
  ret i1 %C1
}

llc crashes. https://godbolt.org/z/vn36qWccj

$ ./bin/llc -mtriple=arm crash/armeb/2/arm-instruction-selection/tracedepth_20__hash_0x-2e90230f449f8a1e/id\:000000\,sig\:11\,src\:010396+017924\,time\:163052514\,execs\:7041568\,op\:libAFLCustomIRMutator.so\,pos\:0.bc
llc: /home/peter/aflplusplus-isel/llvm-fix/llvm/include/llvm/ADT/APInt.h:1339: void llvm::APInt::setBits(unsigned int, unsigned int): Assertion `loBit <= BitWidth && "loBit out of range"' failed.
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace.
Stack dump:
0.      Program arguments: ./bin/llc -mtriple=arm crash/armeb/2/arm-instruction-selection/tracedepth_20__hash_0x-2e90230f449f8a1e/id:000000,sig:11,src:010396+017924,time:163052514,execs:7041568,op:libAFLCustomIRMutator.so,pos:0.bc
1.      Running pass 'Function Pass Manager' on module 'crash/armeb/2/arm-instruction-selection/tracedepth_20__hash_0x-2e90230f449f8a1e/id:000000,sig:11,src:010396+017924,time:163052514,execs:7041568,op:libAFLCustomIRMutator.so,pos:0.bc'.
2.      Running pass 'ARM Instruction Selection' on function '@f'
 #0 0x00007fc51bc6d4ba llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) /home/peter/aflplusplus-isel/llvm-fix/llvm/lib/Support/Unix/Signals.inc:567:11
 #1 0x00007fc51bc6d66b PrintStackTraceSignalHandler(void*) /home/peter/aflplusplus-isel/llvm-fix/llvm/lib/Support/Unix/Signals.inc:641:1
 #2 0x00007fc51bc6bcc6 llvm::sys::RunSignalHandlers() /home/peter/aflplusplus-isel/llvm-fix/llvm/lib/Support/Signals.cpp:104:5
 #3 0x00007fc51bc6dd95 SignalHandler(int) /home/peter/aflplusplus-isel/llvm-fix/llvm/lib/Support/Unix/Signals.inc:412:1
 #4 0x00007fc51a42b980 __restore_rt (/lib/x86_64-linux-gnu/libpthread.so.0+0x12980)
 #5 0x00007fc519727e87 raise /build/glibc-CVJwZb/glibc-2.27/signal/../sysdeps/unix/sysv/linux/raise.c:51:0
 #6 0x00007fc5197297f1 abort /build/glibc-CVJwZb/glibc-2.27/stdlib/abort.c:81:0
 #7 0x00007fc5197193fa __assert_fail_base /build/glibc-CVJwZb/glibc-2.27/assert/assert.c:89:0
 #8 0x00007fc519719472 (/lib/x86_64-linux-gnu/libc.so.6+0x30472)
 #9 0x00007fc52cb9963c llvm::APInt::setBits(unsigned int, unsigned int) /home/peter/aflplusplus-isel/llvm-fix/llvm/include/llvm/ADT/APInt.h:1340:5
#10 0x00007fc52cb99571 llvm::APInt::setHighBits(unsigned int) /home/peter/aflplusplus-isel/llvm-fix/llvm/include/llvm/ADT/APInt.h:1363:5
#11 0x00007fc52cb9923e llvm::APInt::getHighBitsSet(unsigned int, unsigned int) /home/peter/aflplusplus-isel/llvm-fix/llvm/include/llvm/ADT/APInt.h:282:5
#12 0x00007fc52cc32072 PerformSHLSimplify(llvm::SDNode*, llvm::TargetLowering::DAGCombinerInfo&, llvm::ARMSubtarget const*) /home/peter/aflplusplus-isel/llvm-fix/llvm/lib/Target/ARM/ARMISelLowering.cpp:13779:8
#13 0x00007fc52cc087a9 PerformANDCombine(llvm::SDNode*, llvm::TargetLowering::DAGCombinerInfo&, llvm::ARMSubtarget const*) /home/peter/aflplusplus-isel/llvm-fix/llvm/lib/Target/ARM/ARMISelLowering.cpp:14231:26
#14 0x00007fc52cc038ea llvm::ARMTargetLowering::PerformDAGCombine(llvm::SDNode*, llvm::TargetLowering::DAGCombinerInfo&) const /home/peter/aflplusplus-isel/llvm-fix/llvm/lib/Target/ARM/ARMISelLowering.cpp:18620:32
#15 0x00007fc51c09b59f (anonymous namespace)::DAGCombiner::combine(llvm::SDNode*) /home/peter/aflplusplus-isel/llvm-fix/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp:1843:16
#16 0x00007fc51c09aaa6 (anonymous namespace)::DAGCombiner::Run(llvm::CombineLevel) /home/peter/aflplusplus-isel/llvm-fix/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp:1627:18
#17 0x00007fc51c09a38f llvm::SelectionDAG::Combine(llvm::CombineLevel, llvm::AAResults*, llvm::CodeGenOpt::Level) /home/peter/aflplusplus-isel/llvm-fix/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp:25513:3
#18 0x00007fc51c466475 llvm::SelectionDAGISel::CodeGenAndEmitDAG() /home/peter/aflplusplus-isel/llvm-fix/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp:819:5
#19 0x00007fc51c465b5d llvm::SelectionDAGISel::SelectBasicBlock(llvm::ilist_iterator<llvm::ilist_detail::node_options<llvm::Instruction, true, false, void>, false, true>, llvm::ilist_iterator<llvm::ilist_detail::node_options<llvm::Instruction, true, false, void>, false, true>, bool&) /home/peter/aflplusplus-isel/llvm-fix/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp:689:1
#20 0x00007fc51c4655fb llvm::SelectionDAGISel::SelectAllBasicBlocks(llvm::Function const&) /home/peter/aflplusplus-isel/llvm-fix/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp:1604:11
#21 0x00007fc51c462ba6 llvm::SelectionDAGISel::runOnMachineFunction(llvm::MachineFunction&) /home/peter/aflplusplus-isel/llvm-fix/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp:468:3
#22 0x00007fc52cb5dbb5 (anonymous namespace)::ARMDAGToDAGISel::runOnMachineFunction(llvm::MachineFunction&) /home/peter/aflplusplus-isel/llvm-fix/llvm/lib/Target/ARM/ARMISelDAGToDAG.cpp:68:5
#23 0x00007fc51f3fbc35 llvm::MachineFunctionPass::runOnFunction(llvm::Function&) /home/peter/aflplusplus-isel/llvm-fix/llvm/lib/CodeGen/MachineFunctionPass.cpp:91:8
#24 0x00007fc51e5b39e6 llvm::FPPassManager::runOnFunction(llvm::Function&) /home/peter/aflplusplus-isel/llvm-fix/llvm/lib/IR/LegacyPassManager.cpp:1430:23
#25 0x00007fc51e5b8812 llvm::FPPassManager::runOnModule(llvm::Module&) /home/peter/aflplusplus-isel/llvm-fix/llvm/lib/IR/LegacyPassManager.cpp:1476:16
#26 0x00007fc51e5b42b9 (anonymous namespace)::MPPassManager::runOnModule(llvm::Module&) /home/peter/aflplusplus-isel/llvm-fix/llvm/lib/IR/LegacyPassManager.cpp:1545:23
#27 0x00007fc51e5b3e2d llvm::legacy::PassManagerImpl::run(llvm::Module&) /home/peter/aflplusplus-isel/llvm-fix/llvm/lib/IR/LegacyPassManager.cpp:535:16
#28 0x00007fc51e5b8af1 llvm::legacy::PassManager::run(llvm::Module&) /home/peter/aflplusplus-isel/llvm-fix/llvm/lib/IR/LegacyPassManager.cpp:1672:3
#29 0x00000000004199ac compileModule(char**, llvm::LLVMContext&) /home/peter/aflplusplus-isel/llvm-fix/llvm/tools/llc/llc.cpp:736:41
#30 0x0000000000417d52 main /home/peter/aflplusplus-isel/llvm-fix/llvm/tools/llc/llc.cpp:417:13
#31 0x00007fc51970ac87 __libc_start_main /build/glibc-CVJwZb/glibc-2.27/csu/../csu/libc-start.c:344:0
#32 0x000000000041755a _start (./bin/llc+0x41755a)
Aborted

Going to the crashing site, it seems unreasonable to directly subtract bitwidth with the zero extended value, which may get a huge underflowed unsigned value.

https://github.com/llvm/llvm-project/blob/fccab9f90b0327c00116e593351e1e4cd19b5677/llvm/lib/Target/ARM/ARMISelLowering.cpp#L13777-#L13779

Proposed fix:

add a check before the subtract like this:

  if (C2Int.getBitWidth() < C2->getZExtValue()) 
    return SDValue();

Metadata

Metadata

Assignees

Labels

backend:ARMcrashPrefer [crash-on-valid] or [crash-on-invalid]

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions