Skip to content

Commit 011fce8

Browse files
authored
[Runtime] Fix leak of bridge objects in swift_generic_initWithTake (#69977)
rdar://118606044 The initWithTakeTable accidentally referenced bridgeRetain instead of copyingInitWithTake, which caused a leak when an object containing a bridge reference was also not bitwise takable.
1 parent 506fbb3 commit 011fce8

File tree

3 files changed

+60
-1
lines changed

3 files changed

+60
-1
lines changed

stdlib/public/runtime/BytecodeLayouts.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1214,7 +1214,7 @@ constexpr InitFn initWithTakeTable[] = {
12141214
&copyingInitWithTake,
12151215
&copyingInitWithTake,
12161216
&unknownWeakInitWithTake,
1217-
&bridgeRetain,
1217+
&copyingInitWithTake,
12181218
&copyingInitWithTake,
12191219
&copyingInitWithTake,
12201220
nullptr, // Custom

test/Interpreter/Inputs/layout_string_witnesses_types.swift

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -416,6 +416,16 @@ public struct SinglePayloadEnumExtraTagBytesWrapper {
416416
}
417417
}
418418

419+
public struct NotBitwiseTakableBridge<T> {
420+
let x: Int = 0
421+
let y: [T]
422+
weak var z: AnyObject? = nil
423+
424+
public init(_ y: [T]) {
425+
self.y = y
426+
}
427+
}
428+
419429
public enum SinglePayloadEnumExtraTagBytes {
420430
case empty0
421431
case empty1
@@ -603,6 +613,11 @@ public func testInit<T>(_ ptr: UnsafeMutablePointer<T>, to x: T) {
603613
ptr.initialize(to: x)
604614
}
605615

616+
@inline(never)
617+
public func testInitTake<T>(_ ptr: UnsafeMutablePointer<T>, to x: consuming T) {
618+
ptr.initialize(to: consume x)
619+
}
620+
606621
@inline(never)
607622
public func testDestroy<T>(_ ptr: UnsafeMutablePointer<T>) {
608623
ptr.deinitialize(count: 1)

test/Interpreter/layout_string_witnesses_static.swift

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1012,6 +1012,50 @@ func testEnumWithExistential() {
10121012

10131013
testEnumWithExistential()
10141014

1015+
// Regression test for rdar://118606044
1016+
func testNotBitwiseTakableBridge() {
1017+
let ptr = UnsafeMutablePointer<NotBitwiseTakableBridge<SimpleClass>>.allocate(capacity: 1)
1018+
1019+
// initWithTake
1020+
do {
1021+
let x = NotBitwiseTakableBridge([SimpleClass(x: 23)])
1022+
testInitTake(ptr, to: consume x)
1023+
}
1024+
1025+
// assignWithTake
1026+
do {
1027+
let y = NotBitwiseTakableBridge([SimpleClass(x: 33)])
1028+
1029+
// CHECK-NEXT: Before deinit
1030+
print("Before deinit")
1031+
1032+
// CHECK-NEXT: SimpleClass deinitialized!
1033+
testAssign(ptr, from: y)
1034+
}
1035+
1036+
// assignWithCopy
1037+
do {
1038+
var z = NotBitwiseTakableBridge([SimpleClass(x: 43)])
1039+
1040+
// CHECK-NEXT: Before deinit
1041+
print("Before deinit")
1042+
1043+
// CHECK-NEXT: SimpleClass deinitialized!
1044+
testAssignCopy(ptr, from: &z)
1045+
}
1046+
1047+
// CHECK-NEXT: Before deinit
1048+
print("Before deinit")
1049+
1050+
// destroy
1051+
// CHECK-NEXT: SimpleClass deinitialized!
1052+
testDestroy(ptr)
1053+
1054+
ptr.deallocate()
1055+
}
1056+
1057+
testNotBitwiseTakableBridge()
1058+
10151059
#if os(macOS)
10161060
func testObjc() {
10171061
let ptr = UnsafeMutablePointer<ObjcWrapper>.allocate(capacity: 1)

0 commit comments

Comments
 (0)