123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229 |
- // TEST_CFLAGS -Wl,-no_objc_category_merging
- #include "test.h"
- #include "testroot.i"
- #include <string.h>
- #include <objc/runtime.h>
- #if __LP64__
- # define PTR " .quad "
- #else
- # define PTR " .long "
- #endif
- static int state = 0;
- @interface Super : TestRoot @end
- @implementation Super
- -(void)instancemethod { fail("-instancemethod not overridden by category"); }
- +(void)method { fail("+method not overridden by category"); }
- @end
- @interface Super (Category) @end
- @implementation Super (Category)
- +(void)method {
- testprintf("in [Super(Category) method]\n");
- testassert(self == [Super class]);
- testassert(state == 0);
- state = 1;
- }
- -(void)instancemethod {
- testprintf("in [Super(Category) instancemethod]\n");
- testassert(object_getClass(self) == [Super class]);
- testassert(state == 1);
- state = 2;
- }
- @end
- @interface Super (PropertyCategory)
- @property int i;
- @property(class) int i;
- @end
- @implementation Super (PropertyCategory)
- - (int)i { return 0; }
- - (void)setI:(int)value { (void)value; }
- + (int)i { return 0; }
- + (void)setI:(int)value { (void)value; }
- @end
- // rdar://5086110 memory smasher in category with class method and property
- @interface Super (r5086110)
- @property int property5086110;
- @end
- @implementation Super (r5086110)
- +(void)method5086110 {
- fail("method method5086110 called!");
- }
- - (int)property5086110 { fail("property5086110 called!"); return 0; }
- - (void)setProperty5086110:(int)value { fail("setProperty5086110 called!"); (void)value; }
- @end
- // rdar://25605427 incorrect handling of class properties in 10.11 and earlier
- @interface Super25605427 : TestRoot
- @property(class, readonly) int i;
- @end
- @implementation Super25605427
- +(int)i { return 0; }
- @end
- @interface Super25605427 (r25605427a)
- @property(readonly) int r25605427a1;
- @end
- @implementation Super25605427 (r25605427a)
- -(int)r25605427a1 { return 0; }
- +(int)r25605427a2 { return 0; }
- @end
- @interface Super25605427 (r25605427b)
- @property(readonly) int r25605427b1;
- @end
- @implementation Super25605427 (r25605427b)
- -(int)r25605427b1 { return 0; }
- +(int)r25605427b2 { return 0; }
- @end
- @interface Super25605427 (r25605427c)
- @property(readonly) int r25605427c1;
- @end
- @implementation Super25605427 (r25605427c)
- -(int)r25605427c1 { return 0; }
- +(int)r25605427c2 { return 0; }
- @end
- @interface Super25605427 (r25605427d)
- @property(readonly) int r25605427d1;
- @end
- @implementation Super25605427 (r25605427d)
- -(int)r25605427d1 { return 0; }
- +(int)r25605427d2 { return 0; }
- @end
- @interface PropertyClass : Super {
- int q;
- }
- @property(readonly) int q;
- @end
- @implementation PropertyClass
- @synthesize q;
- @end
- @interface PropertyClass (PropertyCategory)
- @property int q;
- @end
- @implementation PropertyClass (PropertyCategory)
- @dynamic q;
- @end
- // Manually build a category that goes in __objc_catlist2.
- #if __has_feature(ptrauth_calls)
- #define SIGNED_CATEGORY_IMP "@AUTH(ia,0,addr)"
- #else
- #define SIGNED_CATEGORY_IMP
- #endif
- asm(
- " .section __DATA,__objc_const \n"
- "L_catlist2CategoryName: \n"
- " .asciz \"Category_catlist2\" \n"
- "L_catlist2MethodString: \n"
- " .asciz \"catlist2Method\" \n"
- "L_catlist2MethodTypes: \n"
- " .asciz \"i16@0:8\" \n"
- " .p2align 3 \n"
- "l_OBJC_$_CATEGORY_INSTANCE_METHODS_Super_$_Category_catlist2: \n"
- " .long 24 \n"
- " .long 1 \n"
- " "PTR" L_catlist2MethodString \n"
- " "PTR" L_catlist2MethodTypes \n"
- " "PTR" _catlist2MethodImplementation"SIGNED_CATEGORY_IMP" \n"
- " .p2align 3 \n"
- "l_OBJC_$_CATEGORY_Super_$_Category_catlist2: \n"
- " "PTR" L_catlist2CategoryName \n"
- " "PTR" _OBJC_CLASS_$_Super \n"
- " "PTR" l_OBJC_$_CATEGORY_INSTANCE_METHODS_Super_$_Category_catlist2 \n"
- " "PTR" 0 \n"
- " "PTR" 0 \n"
- " "PTR" 0 \n"
- " "PTR" 0 \n"
- " .long 64 \n"
- " .space 4 \n"
- " .section __DATA,__objc_catlist2 \n"
- " .p2align 3 \n"
- " "PTR" l_OBJC_$_CATEGORY_Super_$_Category_catlist2 \n"
- " .text \n"
- );
- @interface Super (Category_catlist2)
- - (int)catlist2Method;
- @end
- EXTERN_C int catlist2MethodImplementation(id self __unused, SEL _cmd __unused) {
- return 0;
- }
- int main()
- {
- {
- // rdar://25605427 bugs in 10.11 and earlier when metaclass
- // has a property and category has metaclass additions.
- // Memory smasher in buildPropertyList (caught by guard malloc)
- Class cls = [Super25605427 class];
- // Incorrect attachment of instance properties from category to metacls
- testassert(class_getProperty(cls, "r25605427d1"));
- testassert(! class_getProperty(object_getClass(cls), "r25605427d1"));
- }
- // methods introduced by category
- state = 0;
- [Super method];
- [[Super new] instancemethod];
- testassert(state == 2);
- // property introduced by category
- objc_property_t p = class_getProperty([Super class], "i");
- testassert(p);
- testassert(0 == strcmp(property_getName(p), "i"));
- testassert(property_getAttributes(p));
- objc_property_t p2 = class_getProperty(object_getClass([Super class]), "i");
- testassert(p2);
- testassert(p != p2);
- testassert(0 == strcmp(property_getName(p2), "i"));
- testassert(property_getAttributes(p2));
- // methods introduced by category's property
- Method m;
- m = class_getInstanceMethod([Super class], @selector(i));
- testassert(m);
- m = class_getInstanceMethod([Super class], @selector(setI:));
- testassert(m);
- m = class_getClassMethod([Super class], @selector(i));
- testassert(m);
- m = class_getClassMethod([Super class], @selector(setI:));
- testassert(m);
- // class's property shadowed by category's property
- objc_property_t *plist = class_copyPropertyList([PropertyClass class], NULL);
- testassert(plist);
- testassert(plist[0]);
- testassert(0 == strcmp(property_getName(plist[0]), "q"));
- testassert(0 == strcmp(property_getAttributes(plist[0]), "Ti,D"));
- testassert(plist[1]);
- testassert(0 == strcmp(property_getName(plist[1]), "q"));
- testassert(0 == strcmp(property_getAttributes(plist[1]), "Ti,R,Vq"));
- testassert(!plist[2]);
- free(plist);
-
- // method introduced by category in catlist2
- testassert([[Super new] catlist2Method] == 0);
-
- succeed(__FILE__);
- }
|