Skip to content

Commit 56777e7

Browse files
authored
[SimplifyCFG] Avoid use-after-free when removing incoming values from PHI nodes (#165744)
`PHINode::removeIncomingValue` removes itself when there are no incoming edges. Then we cannot use it to retrieve the next instruction. Closes #165301.
1 parent 6ba2127 commit 56777e7

File tree

2 files changed

+30
-4
lines changed

2 files changed

+30
-4
lines changed

llvm/lib/Transforms/Utils/SimplifyCFG.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5977,14 +5977,14 @@ bool SimplifyCFGOpt::turnSwitchRangeIntoICmp(SwitchInst *SI,
59775977
}
59785978

59795979
// Prune obsolete incoming values off the successors' PHI nodes.
5980-
for (auto BBI = Dest->begin(); isa<PHINode>(BBI); ++BBI) {
5980+
for (auto &PHI : make_early_inc_range(Dest->phis())) {
59815981
unsigned PreviousEdges = Cases->size();
59825982
if (Dest == SI->getDefaultDest())
59835983
++PreviousEdges;
59845984
for (unsigned I = 0, E = PreviousEdges - 1; I != E; ++I)
5985-
cast<PHINode>(BBI)->removeIncomingValue(SI->getParent());
5985+
PHI.removeIncomingValue(SI->getParent());
59865986
}
5987-
for (auto BBI = OtherDest->begin(); isa<PHINode>(BBI); ++BBI) {
5987+
for (auto &PHI : make_early_inc_range(OtherDest->phis())) {
59885988
unsigned PreviousEdges = OtherCases->size();
59895989
if (OtherDest == SI->getDefaultDest())
59905990
++PreviousEdges;
@@ -5993,7 +5993,7 @@ bool SimplifyCFGOpt::turnSwitchRangeIntoICmp(SwitchInst *SI,
59935993
if (NewBI->isUnconditional())
59945994
++E;
59955995
for (unsigned I = 0; I != E; ++I)
5996-
cast<PHINode>(BBI)->removeIncomingValue(SI->getParent());
5996+
PHI.removeIncomingValue(SI->getParent());
59975997
}
59985998

59995999
// Clean up the default block - it may have phis or other instructions before
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
2+
; RUN: opt -S -passes="simplifycfg<switch-range-to-icmp>" < %s | FileCheck %s
3+
4+
; Make sure there's no use after free when removing incoming values from PHI nodes
5+
6+
define i32 @pr165301(i1 %cond) {
7+
; CHECK-LABEL: define i32 @pr165301(
8+
; CHECK-SAME: i1 [[COND:%.*]]) {
9+
; CHECK-NEXT: [[ENTRY:.*:]]
10+
; CHECK-NEXT: br label %[[SWITCHBB:.*]]
11+
; CHECK: [[SWITCHBB]]:
12+
; CHECK-NEXT: br label %[[SWITCHBB]]
13+
;
14+
entry:
15+
br label %switchbb
16+
17+
switchbb:
18+
switch i1 %cond, label %default [
19+
i1 false, label %switchbb
20+
i1 true, label %switchbb
21+
]
22+
23+
default:
24+
%phi.lcssa = phi i32 [ 0, %switchbb ]
25+
ret i32 %phi.lcssa
26+
}

0 commit comments

Comments
 (0)