]> granicus.if.org Git - llvm/commitdiff
Merging r369168:
authorHans Wennborg <hans@hanshq.net>
Tue, 20 Aug 2019 09:45:09 +0000 (09:45 +0000)
committerHans Wennborg <hans@hanshq.net>
Tue, 20 Aug 2019 09:45:09 +0000 (09:45 +0000)
------------------------------------------------------------------------
r369168 | spatel | 2019-08-17 01:10:34 +0200 (Sat, 17 Aug 2019) | 16 lines

[CodeGenPrepare] Fix use-after-free

If OptimizeExtractBits() encountered a shift instruction with no operands at all,
it would erase the instruction, but still return false.

This previously didn’t matter because its caller would always return after
processing the instruction, but https://reviews.llvm.org/D63233 changed the
function’s caller to fall through if it returned false, which would then cause
a use-after-free detectable by ASAN.

This change makes OptimizeExtractBits return true if it removes a shift
instruction with no users, terminating processing of the instruction.

Patch by: @brentdax (Brent Royal-Gordon)

Differential Revision: https://reviews.llvm.org/D66330
------------------------------------------------------------------------

git-svn-id: https://llvm.org/svn/llvm-project/llvm/branches/release_90@369355 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CodeGenPrepare.cpp
test/Transforms/CodeGenPrepare/sink-shift-and-trunc.ll

index 52b4bbea012bc5ad033e2da376ac70fc34319293..e6f2aa9ef9305611dbcc48e6f4ea0f28846e7386 100644 (file)
@@ -1682,10 +1682,11 @@ static bool OptimizeExtractBits(BinaryOperator *ShiftI, ConstantInt *CI,
     TheUse = InsertedShift;
   }
 
-  // If we removed all uses, nuke the shift.
+  // If we removed all uses, or there are none, nuke the shift.
   if (ShiftI->use_empty()) {
     salvageDebugInfo(*ShiftI);
     ShiftI->eraseFromParent();
+    MadeChange = true;
   }
 
   return MadeChange;
index 20a436edd105c67ed757a2a5f377fc64570f8ffc..609b6bf679a25d0dd7cc81114b1c2c030eb6731a 100644 (file)
@@ -58,6 +58,23 @@ return:                                           ; preds = %if.then17, %if.end1
   ret i32 %retval.0, !dbg !63
 }
 
+; CodeGenPrepare was erasing the unused lshr instruction, but then further
+; processing the instruction after it was freed. If this bug is still present,
+; this test will always crash in an LLVM built with ASAN enabled, and may
+; crash even if ASAN is not enabled.
+
+define i32 @shift_unused(i32 %a) {
+; CHECK-LABEL: @shift_unused(
+; CHECK-NEXT:  BB2:
+; CHECK-NEXT:    ret i32 [[A:%.*]]
+;
+  %as = lshr i32 %a, 3
+  br label %BB2
+
+BB2:
+  ret i32 %a
+}
+
 ; CHECK: [[shift1_loc]] = !DILocation(line: 1
 ; CHECK: [[trunc1_loc]] = !DILocation(line: 2
 ; CHECK: [[shift2_loc]] = !DILocation(line: 3