Skip to content

Commit a069727

Browse files
authored
Retrieve class of instance in objc_alloc_init (#315)
If +alloc was overwritten, it is not guaranteed that it returns an instance of cls. Retrieve the class of the instance returned by objc_alloc instead.
1 parent 771f7c4 commit a069727

File tree

2 files changed

+16
-3
lines changed

2 files changed

+16
-3
lines changed

Test/FastPathAlloc.m

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ @interface NoAlloc : Test @end
2121
@interface NoInit : Test @end
2222
@interface NoInit2 : NoInit @end
2323

24+
@interface ShouldInitSubclassed : NoInit @end
25+
2426
@implementation ShouldAlloc
2527
+ (instancetype)alloc
2628
{
@@ -91,6 +93,13 @@ + (instancetype)alloc
9193
}
9294
@end
9395

96+
@implementation ShouldInitSubclassed
97+
+ (instancetype) alloc
98+
{
99+
return [ShouldInit alloc];
100+
}
101+
@end
102+
94103
Class getClassNamed(char *name)
95104
{
96105
return nil;
@@ -114,6 +123,10 @@ int main(void)
114123
[[ShouldInit2 alloc] init];
115124
assert(called);
116125

126+
called = NO;
127+
[[ShouldInitSubclassed alloc] init];
128+
assert(called);
129+
117130
called = NO;
118131
[NoAlloc alloc];
119132
assert(!called);

fast_paths.m

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,6 @@ - (id)init;
99
@end
1010
#include <stdio.h>
1111

12-
/**
13-
* Equivalent to [cls alloc]. If there's a fast path opt-in, then this skips the message send.
14-
*/
1512
OBJC_PUBLIC
1613
id
1714
objc_alloc(Class cls)
@@ -66,6 +63,9 @@ - (id)init;
6663
return nil;
6764
}
6865
id instance = objc_alloc(cls);
66+
// If +alloc was overwritten, it is not guaranteed that it returns
67+
// an instance of cls.
68+
cls = classForObject(instance);
6969
if (objc_test_class_flag(cls, objc_class_flag_fast_alloc_init))
7070
{
7171
return instance;

0 commit comments

Comments
 (0)