@@ -542,6 +542,26 @@ typedef SWIFT_CC(swift) NSDictionary *(*GetErrorDefaultUserInfoFunction)(
542542
543543extern " C" const ProtocolDescriptor PROTOCOL_DESCR_SYM (s5Error);
544544
545+ static IMP
546+ getNSProxyLookupMethod () {
547+ Class NSProxyClass = objc_lookUpClass (" NSProxy" );
548+ return class_getMethodImplementation (NSProxyClass, @selector (methodSignatureForSelector: ));
549+ }
550+
551+ // A safer alternative to calling `isKindOfClass:` directly.
552+ static bool
553+ isKindOfClass (HeapObject *object, Class cls) {
554+ IMP NSProxyLookupMethod = SWIFT_LAZY_CONSTANT (getNSProxyLookupMethod ());
555+ // People sometimes fail to override `methodSignatureForSelector:` in their
556+ // NSProxy subclasses, which causes `isKindOfClass:` to crash. Avoid that...
557+ Class objectClass = object_getClass ((id )object);
558+ IMP objectLookupMethod = class_getMethodImplementation (objectClass, @selector (methodSignatureForSelector: ));
559+ if (objectLookupMethod == NSProxyLookupMethod) {
560+ return false ;
561+ }
562+ return [reinterpret_cast<id >(object) isKindOfClass: cls];
563+ }
564+
545565bool
546566swift::tryDynamicCastNSErrorObjectToValue (HeapObject *object,
547567 OpaqueValue *dest,
@@ -550,8 +570,7 @@ typedef SWIFT_CC(swift) NSDictionary *(*GetErrorDefaultUserInfoFunction)(
550570 Class NSErrorClass = getNSErrorClass ();
551571
552572 // The object must be an NSError subclass.
553- if (isObjCTaggedPointerOrNull (object) ||
554- ![reinterpret_cast<id >(object) isKindOfClass: NSErrorClass])
573+ if (isObjCTaggedPointerOrNull (object) || !isKindOfClass (object, NSErrorClass))
555574 return false ;
556575
557576 id srcInstance = reinterpret_cast <id >(object);
0 commit comments