@@ -542,6 +542,26 @@ typedef SWIFT_CC(swift) NSDictionary *(*GetErrorDefaultUserInfoFunction)(
542
542
543
543
extern " C" const ProtocolDescriptor PROTOCOL_DESCR_SYM (s5Error);
544
544
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
+
545
565
bool
546
566
swift::tryDynamicCastNSErrorObjectToValue (HeapObject *object,
547
567
OpaqueValue *dest,
@@ -550,8 +570,7 @@ typedef SWIFT_CC(swift) NSDictionary *(*GetErrorDefaultUserInfoFunction)(
550
570
Class NSErrorClass = getNSErrorClass ();
551
571
552
572
// 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))
555
574
return false ;
556
575
557
576
id srcInstance = reinterpret_cast <id >(object);
0 commit comments