Skip to content

Commit a5bb53a

Browse files
committed
[Runtime] Properly compute offset for unmanaged properties in generic CVW instantiation
rdar://137066879 An unmanaged property does not map to an operation in CVW, instead it will be copied like primitive values. When instantiating the layout string, we correctly do not emit an operation, but we compute the offset to the next field as if we did. This is causing the offset to be incorrect and subsequent operations to be executed on the wrong address, causing crashes or other misbehavior.
1 parent 4e32b60 commit a5bb53a

File tree

3 files changed

+42
-2
lines changed

3 files changed

+42
-2
lines changed

stdlib/public/runtime/Metadata.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2852,11 +2852,12 @@ void swift::swift_initStructMetadataWithLayoutString(
28522852

28532853
auto tagAndOffset = ((uint64_t)tag << 56) | offset;
28542854
writer.writeBytes(tagAndOffset);
2855+
previousFieldOffset = fieldType->size - sizeof(uintptr_t);
2856+
} else {
2857+
previousFieldOffset += fieldType->size;
28552858
}
28562859

28572860
fullOffset += fieldType->size;
2858-
previousFieldOffset = fieldType->size - sizeof(uintptr_t);
2859-
28602861
continue;
28612862
}
28622863

test/Interpreter/Inputs/layout_string_witnesses_types_resilient.swift

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,17 @@ public struct GenericResilient<C, T> {
1919
}
2020
}
2121

22+
public struct GenericResilientWithUnmanagedAndWeak<T> {
23+
public let x: T
24+
public unowned(unsafe) var y: AnyObject?
25+
public let z: Int = 500
26+
public weak var w: AnyObject?
27+
28+
public init(x: T) {
29+
self.x = x
30+
}
31+
}
32+
2233
public enum ResilientSinglePayloadEnumGeneric<T> {
2334
case empty0
2435
case empty1

test/Interpreter/layout_string_witnesses_dynamic.swift

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1209,6 +1209,34 @@ func testWeakRefOptionalNative() {
12091209

12101210
testWeakRefOptionalNative()
12111211

1212+
func testGenericResilientWithUnmanagedAndWeak() {
1213+
let ptr = allocateInternalGenericPtr(of: GenericResilientWithUnmanagedAndWeak<TestClass>.self)
1214+
1215+
do {
1216+
let x = GenericResilientWithUnmanagedAndWeak<TestClass>(x: TestClass())
1217+
testGenericInit(ptr, to: x)
1218+
}
1219+
1220+
do {
1221+
let y = GenericResilientWithUnmanagedAndWeak<TestClass>(x: TestClass())
1222+
// CHECK: Before deinit
1223+
print("Before deinit")
1224+
1225+
// CHECK-NEXT: TestClass deinitialized!
1226+
testGenericAssign(ptr, from: y)
1227+
}
1228+
1229+
// CHECK-NEXT: Before deinit
1230+
print("Before deinit")
1231+
1232+
// CHECK-NEXT: TestClass deinitialized!
1233+
testGenericDestroy(ptr, of: GenericResilientWithUnmanagedAndWeak<TestClass>.self)
1234+
1235+
ptr.deallocate()
1236+
}
1237+
1238+
testGenericResilientWithUnmanagedAndWeak()
1239+
12121240
#if os(macOS)
12131241

12141242
import Foundation

0 commit comments

Comments
 (0)