Skip to content

Commit 0a21c4d

Browse files
authored
Fix another use-after-free in SILCombine (#34168)
* Fix another use-after-free in SILCombine swift::endLifetimeAtFrontier also needs to use swift::emitDestroyOperation and delete instructions via callbacks that can correctly remove it from the worklist that SILCombine maintains * Add test for use-after-free in SILCombine
1 parent 6d599ea commit 0a21c4d

File tree

5 files changed

+39
-12
lines changed

5 files changed

+39
-12
lines changed

include/swift/SILOptimizer/Utils/ValueLifetime.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,9 @@
1717
#ifndef SWIFT_SILOPTIMIZER_UTILS_CFG_H
1818
#define SWIFT_SILOPTIMIZER_UTILS_CFG_H
1919

20-
#include "swift/SIL/SILInstruction.h"
2120
#include "swift/SIL/SILBuilder.h"
21+
#include "swift/SIL/SILInstruction.h"
22+
#include "swift/SILOptimizer/Utils/InstOptUtils.h"
2223

2324
namespace swift {
2425

@@ -159,7 +160,8 @@ class ValueLifetimeAnalysis {
159160
/// destroy_value at each instruction of the \p frontier.
160161
void endLifetimeAtFrontier(SILValue valueOrStackLoc,
161162
const ValueLifetimeAnalysis::Frontier &frontier,
162-
SILBuilderContext &builderCtxt);
163+
SILBuilderContext &builderCtxt,
164+
InstModCallbacks callbacks);
163165

164166
} // end namespace swift
165167

lib/SILOptimizer/Utils/InstOptUtils.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1323,7 +1323,8 @@ bool swift::collectDestroys(SingleValueInstruction *inst,
13231323
/// not be needed anymore with OSSA.
13241324
static bool keepArgsOfPartialApplyAlive(PartialApplyInst *pai,
13251325
ArrayRef<SILInstruction *> paiUsers,
1326-
SILBuilderContext &builderCtxt) {
1326+
SILBuilderContext &builderCtxt,
1327+
InstModCallbacks callbacks) {
13271328
SmallVector<Operand *, 8> argsToHandle;
13281329
getConsumedPartialApplyArgs(pai, argsToHandle,
13291330
/*includeTrivialAddrArgs*/ false);
@@ -1357,7 +1358,7 @@ static bool keepArgsOfPartialApplyAlive(PartialApplyInst *pai,
13571358

13581359
// Delay the destroy of the value (either as SSA value or in the stack-
13591360
// allocated temporary) at the end of the partial_apply's lifetime.
1360-
endLifetimeAtFrontier(tmp, partialApplyFrontier, builderCtxt);
1361+
endLifetimeAtFrontier(tmp, partialApplyFrontier, builderCtxt, callbacks);
13611362
}
13621363
return true;
13631364
}
@@ -1406,7 +1407,8 @@ bool swift::tryDeleteDeadClosure(SingleValueInstruction *closure,
14061407
"partial_apply [stack] should have been handled before");
14071408
SILBuilderContext builderCtxt(pai->getModule());
14081409
if (needKeepArgsAlive) {
1409-
if (!keepArgsOfPartialApplyAlive(pai, closureDestroys, builderCtxt))
1410+
if (!keepArgsOfPartialApplyAlive(pai, closureDestroys, builderCtxt,
1411+
callbacks))
14101412
return false;
14111413
} else {
14121414
// A preceeding partial_apply -> apply conversion (done in

lib/SILOptimizer/Utils/PartialApplyCombiner.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ bool PartialApplyCombiner::copyArgsToTemporaries(
115115

116116
// Destroy the argument value (either as SSA value or in the stack-
117117
// allocated temporary) at the end of the partial_apply's lifetime.
118-
endLifetimeAtFrontier(tmp, partialApplyFrontier, builderCtxt);
118+
endLifetimeAtFrontier(tmp, partialApplyFrontier, builderCtxt, callbacks);
119119
}
120120
return true;
121121
}

lib/SILOptimizer/Utils/ValueLifetime.cpp

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -327,15 +327,12 @@ void ValueLifetimeAnalysis::dump() const {
327327

328328
void swift::endLifetimeAtFrontier(
329329
SILValue valueOrStackLoc, const ValueLifetimeAnalysis::Frontier &frontier,
330-
SILBuilderContext &builderCtxt) {
330+
SILBuilderContext &builderCtxt, InstModCallbacks callbacks) {
331331
for (SILInstruction *endPoint : frontier) {
332332
SILBuilderWithScope builder(endPoint, builderCtxt);
333333
SILLocation loc = RegularLocation(endPoint->getLoc().getSourceLoc());
334-
if (valueOrStackLoc->getType().isObject()) {
335-
builder.emitDestroyValueOperation(loc, valueOrStackLoc);
336-
} else {
337-
assert(isa<AllocStackInst>(valueOrStackLoc));
338-
builder.createDestroyAddr(loc, valueOrStackLoc);
334+
emitDestroyOperation(builder, loc, valueOrStackLoc, callbacks);
335+
if (isa<AllocStackInst>(valueOrStackLoc)) {
339336
builder.createDeallocStack(loc, valueOrStackLoc);
340337
}
341338
}

test/SILOptimizer/sil_combine_apply.sil

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -991,3 +991,29 @@ sil @test_partial_apply_method : $@convention(thin) () -> @owned @callee_owned (
991991
// CHECK: [[FN:%.*]] = function_ref @method
992992
// CHECK-NEXT: partial_apply [[FN]]()
993993
// CHECK-NEXT: return
994+
995+
sil [noinline] @$foo : $@convention(thin) (@owned { var Int64 }) -> ()
996+
997+
// CHECK-LABEL: sil private [noinline] @$testdeadpartialapply :
998+
// CHECK-NOT: partial_apply
999+
// CHECK-LABEL: } // end sil function '$testdeadpartialapply'
1000+
sil private [noinline] @$testdeadpartialapply : $@convention(thin) (@owned { var Int64 }) -> () {
1001+
bb0(%0 : ${ var Int64 }):
1002+
%3 = function_ref @$foo : $@convention(thin) (@owned { var Int64 }) -> ()
1003+
%5 = partial_apply [callee_guaranteed] %3(%0) : $@convention(thin) (@owned { var Int64 }) -> ()
1004+
cond_br undef, bb1, bb2
1005+
bb1:
1006+
strong_retain %0 : ${ var Int64 }
1007+
strong_retain %5 : $@callee_guaranteed () -> ()
1008+
unreachable
1009+
bb2:
1010+
strong_retain %0 : ${ var Int64 }
1011+
strong_retain %5 : $@callee_guaranteed () -> ()
1012+
br bb3
1013+
bb3:
1014+
strong_release %5 : $@callee_guaranteed () -> ()
1015+
strong_release %5 : $@callee_guaranteed () -> ()
1016+
strong_release %0 : ${ var Int64 }
1017+
%rv = tuple()
1018+
return %rv : $()
1019+
}

0 commit comments

Comments
 (0)