From 3a396af086a0fd4152110aafa84a81af6b7a042c Mon Sep 17 00:00:00 2001 From: Mike Ash Date: Mon, 8 May 2023 16:37:41 -0400 Subject: [PATCH] [Runtime] Immediate release and return when destroying partial instance of pure ObjC class. Make swift_deallocPartialClassInstance check if the object's class is a pure ObjC class, in which case there are no ivar destroyers and we can just return immediately. It's possible for an allocWithZone: override to cause self to be a special object constructed in read-only memory. swift_deallocPartialClassInstance calls object_setClass to avoid running the dealloc method of any Swift subclasses, but this call crashes if self is read-only. It's unnecessary when the object's class is pure ObjC and therefore there are no Swift subclasses, so just skip it entirely. rdar://107756747 --- stdlib/public/runtime/HeapObject.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/stdlib/public/runtime/HeapObject.cpp b/stdlib/public/runtime/HeapObject.cpp index 3497fc2b75234..5a69aeb1baa44 100644 --- a/stdlib/public/runtime/HeapObject.cpp +++ b/stdlib/public/runtime/HeapObject.cpp @@ -849,6 +849,17 @@ void swift::swift_deallocPartialClassInstance(HeapObject *object, // Destroy ivars auto *classMetadata = _swift_getClassOfAllocated(object)->getClassObject(); assert(classMetadata && "Not a class?"); + +#if SWIFT_OBJC_INTEROP + // If the object's class is already pure ObjC class, just release it and move + // on. There are no ivar destroyers. This avoids attempting to mutate + // placeholder objects statically created in read-only memory. + if (classMetadata->isPureObjC()) { + objc_release((id)object); + return; + } +#endif + while (classMetadata != metadata) { #if SWIFT_OBJC_INTEROP // If we have hit a pure Objective-C class, we won't see another ivar