Skip to content

Commit 9618083

Browse files
authored
Merge pull request #63114 from tshortli/back-deploy-double-free
SILGen: Fix double-free of `__owned` parameters of functions with `@_backDeploy`
2 parents 2010955 + 9f54e9c commit 9618083

File tree

3 files changed

+67
-17
lines changed

3 files changed

+67
-17
lines changed

lib/SILGen/SILGenBackDeploy.cpp

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -178,20 +178,28 @@ void SILGenFunction::emitBackDeploymentThunk(SILDeclRef thunk) {
178178

179179
F.setGenericEnvironment(SGM.Types.getConstantGenericEnvironment(thunk));
180180

181-
emitBasicProlog(FD->getParameters(), FD->getImplicitSelfDecl(),
182-
FD->getResultInterfaceType(), FD, FD->hasThrows(),
183-
FD->getThrowsLoc());
184-
prepareEpilog(FD->getResultInterfaceType(), FD->hasThrows(),
185-
CleanupLocation(FD));
181+
// Generate the thunk prolog by collecting parameters.
182+
SmallVector<ManagedValue, 4> params;
183+
SmallVector<SILArgument *, 4> indirectParams;
184+
collectThunkParams(loc, params, &indirectParams);
186185

187-
// Gather the entry block's arguments up so that we can forward them.
186+
// Build up the list of arguments that we're going to invoke the the real
187+
// function with.
188188
SmallVector<SILValue, 8> paramsForForwarding;
189-
SILBasicBlock *entryBlock = getFunction().getEntryBlock();
190-
for (SILArgument *arg :
191-
make_range(entryBlock->args_begin(), entryBlock->args_end())) {
192-
paramsForForwarding.emplace_back(arg);
189+
for (auto indirectParam : indirectParams) {
190+
paramsForForwarding.emplace_back(indirectParam);
191+
}
192+
193+
for (auto param : params) {
194+
// We're going to directly call either the original function or the fallback
195+
// function with these arguments and then return. Therefore we just forward
196+
// the arguments instead of handling their ownership conventions.
197+
paramsForForwarding.emplace_back(param.forward(*this));
193198
}
194199

200+
prepareEpilog(FD->getResultInterfaceType(), FD->hasThrows(),
201+
CleanupLocation(FD));
202+
195203
SILBasicBlock *availableBB = createBasicBlock("availableBB");
196204
SILBasicBlock *unavailableBB = createBasicBlock("unavailableBB");
197205

test/SILGen/back_deploy_attribute_generic_func.swift

Lines changed: 47 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,14 @@
55

66
// REQUIRES: OS=macosx
77

8-
// -- Fallback definition of genericFunc()
8+
// -- Fallback definition of genericFunc(_:)
99
// CHECK-LABEL: sil non_abi [serialized] [ossa] @$s11back_deploy11genericFuncyxxlFTwB : $@convention(thin) <T> (@in_guaranteed T) -> @out T
1010
// CHECK: bb0([[OUT_ARG:%.*]] : $*T, [[IN_ARG:%.*]] : $*T):
1111
// CHECK: copy_addr [[IN_ARG]] to [init] [[OUT_ARG]] : $*T
1212
// CHECK: [[RESULT:%.*]] = tuple ()
1313
// CHECK: return [[RESULT]] : $()
1414

15-
// -- Back deployment thunk for genericFunc()
15+
// -- Back deployment thunk for genericFunc(_:)
1616
// CHECK-LABEL: sil non_abi [serialized] [thunk] [ossa] @$s11back_deploy11genericFuncyxxlFTwb : $@convention(thin) <T> (@in_guaranteed T) -> @out T
1717
// CHECK: bb0([[OUT_ARG:%.*]] : $*T, [[IN_ARG:%.*]] : $*T):
1818
// CHECK: [[MAJOR:%.*]] = integer_literal $Builtin.Word, 10
@@ -36,16 +36,58 @@
3636
// CHECK: [[RESULT:%.*]] = tuple ()
3737
// CHECK: return [[RESULT]] : $()
3838

39-
// -- Original definition of genericFunc()
39+
// -- Original definition of genericFunc(_:)
4040
// CHECK-LABEL: sil [available 10.52] [ossa] @$s11back_deploy11genericFuncyxxlF : $@convention(thin) <T> (@in_guaranteed T) -> @out T
4141
@_backDeploy(before: macOS 10.52)
4242
public func genericFunc<T>(_ t: T) -> T {
4343
return t
4444
}
4545

46+
// -- Fallback definition of genericFuncWithOwnedParam(_:)
47+
// CHECK-LABEL: sil non_abi [serialized] [ossa] @$s11back_deploy25genericFuncWithOwnedParamyyxnlFTwB : $@convention(thin) <T> (@in T) -> ()
48+
// CHECK: bb0([[IN_ARG:%.*]] : $*T):
49+
// CHECK: destroy_addr [[IN_ARG]] : $*T
50+
// CHECK: [[RESULT:%.*]] = tuple ()
51+
// CHECK: return [[RESULT]] : $()
52+
53+
// -- Back deployment thunk for genericFuncWithOwnedParam(_:)
54+
// CHECK-LABEL: sil non_abi [serialized] [thunk] [ossa] @$s11back_deploy25genericFuncWithOwnedParamyyxnlFTwb : $@convention(thin) <T> (@in T) -> ()
55+
// CHECK: bb0([[IN_ARG:%.*]] : $*T):
56+
// CHECK: [[MAJOR:%.*]] = integer_literal $Builtin.Word, 10
57+
// CHECK: [[MINOR:%.*]] = integer_literal $Builtin.Word, 52
58+
// CHECK: [[PATCH:%.*]] = integer_literal $Builtin.Word, 0
59+
// CHECK: [[OSVFN:%.*]] = function_ref @$ss26_stdlib_isOSVersionAtLeastyBi1_Bw_BwBwtF : $@convention(thin) (Builtin.Word, Builtin.Word, Builtin.Word) -> Builtin.Int1
60+
// CHECK: [[AVAIL:%.*]] = apply [[OSVFN]]([[MAJOR]], [[MINOR]], [[PATCH]]) : $@convention(thin) (Builtin.Word, Builtin.Word, Builtin.Word) -> Builtin.Int1
61+
// CHECK: cond_br [[AVAIL]], [[AVAIL_BB:bb[0-9]+]], [[UNAVAIL_BB:bb[0-9]+]]
62+
//
63+
// CHECK: [[UNAVAIL_BB]]:
64+
// CHECK: [[FALLBACKFN:%.*]] = function_ref @$s11back_deploy25genericFuncWithOwnedParamyyxnlFTwB : $@convention(thin) <τ_0_0> (@in τ_0_0) -> ()
65+
// CHECK: {{%.*}} = apply [[FALLBACKFN]]<T>([[IN_ARG]]) : $@convention(thin) <τ_0_0> (@in τ_0_0) -> ()
66+
// CHECK: br [[RETURN_BB:bb[0-9]+]]
67+
//
68+
// CHECK: [[AVAIL_BB]]:
69+
// CHECK: [[ORIGFN:%.*]] = function_ref @$s11back_deploy25genericFuncWithOwnedParamyyxnlF : $@convention(thin) <τ_0_0> (@in τ_0_0) -> ()
70+
// CHECK: {{%.*}} = apply [[ORIGFN]]<T>([[IN_ARG]]) : $@convention(thin) <τ_0_0> (@in τ_0_0) -> ()
71+
// CHECK: br [[RETURN_BB]]
72+
//
73+
// CHECK: [[RETURN_BB]]
74+
// CHECK-NOT: destroy_addr
75+
// CHECK: [[RESULT:%.*]] = tuple ()
76+
// CHECK: return [[RESULT]] : $()
77+
78+
// -- Original definition of genericFuncWithOwnedParam(_:)
79+
// CHECK-LABEL: sil [available 10.52] [ossa] @$s11back_deploy25genericFuncWithOwnedParamyyxnlF : $@convention(thin) <T> (@in T) -> ()
80+
@_backDeploy(before: macOS 10.52)
81+
public func genericFuncWithOwnedParam<T>(_ t: __owned T) { }
82+
83+
struct S {}
84+
4685
// CHECK-LABEL: sil hidden [ossa] @$s11back_deploy6calleryyF : $@convention(thin) () -> ()
4786
func caller() {
48-
// -- Verify the thunk is called
87+
// -- Verify the thunks are called
4988
// CHECK: {{%.*}} = function_ref @$s11back_deploy11genericFuncyxxlFTwb : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0) -> @out τ_0_0
50-
_ = genericFunc(Int32(1))
89+
_ = genericFunc(S())
90+
91+
// CHECK: {{%.*}} = function_ref @$s11back_deploy25genericFuncWithOwnedParamyyxnlFTwb : $@convention(thin) <τ_0_0> (@in τ_0_0) -> ()
92+
genericFuncWithOwnedParam(S())
5193
}

test/attr/Inputs/BackDeployHelper.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ public func v2APIsAreStripped() -> Bool {
3535
/// Describes types that can be appended to.
3636
public protocol Appendable {
3737
associatedtype Element
38-
mutating func append(_ x: Element)
38+
mutating func append(_ x: __owned Element)
3939
}
4040

4141
/// Describes types that can be counted.
@@ -107,7 +107,7 @@ public func pleaseThrow(_ shouldThrow: Bool) throws -> Bool {
107107
@_backDeploy(before: BackDeploy 2.0)
108108
public func genericAppend<T: Appendable>(
109109
_ a: inout T,
110-
_ x: T.Element
110+
_ x: __owned T.Element
111111
) {
112112
return a.append(x)
113113
}

0 commit comments

Comments
 (0)