From f264fd159d5d1624d822612ec4f7f05cb01df117 Mon Sep 17 00:00:00 2001 From: Niels Grewe Date: Mon, 8 Feb 2016 20:42:57 +0100 Subject: [PATCH] Fix a segfault on (s|g)etting ivars. When we were trying to get or set an ivar on a class that had no ivars defined, we'd dereference a NULL ivar list while determining the ownership qualifier. --- Test/ivar_arc.m | 31 ++++++++++++++++++++++++++++--- ivar.c | 3 ++- 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/Test/ivar_arc.m b/Test/ivar_arc.m index d45775d..0f719e5 100644 --- a/Test/ivar_arc.m +++ b/Test/ivar_arc.m @@ -20,14 +20,29 @@ int dealloc = 0; } @end +@interface EmptySubFoo : Foo +@end + +@implementation EmptySubFoo +@end + +@interface NonEmptySubFoo : Foo +{ + __strong id ignored; +} +@end + +@implementation NonEmptySubFoo +@end + void setIvar(id obj, const char * name, id val) { object_setIvar(obj, class_getInstanceVariable(object_getClass(obj), name), val); } -int main(void) +void testIvarsOn(Foo* f) { - Foo *f = [Foo new]; + dealloc = 0; Dealloc *d = [Dealloc new]; __unsafe_unretained Dealloc *dead; setIvar(f, "w", d); @@ -48,5 +63,15 @@ int main(void) setIvar(f, "s", nil); assert(dealloc == 1); assert(f->s == nil); - return 0; +} + +int main (void) +{ + /* Test for ivars in the same class */ + testIvarsOn([Foo new]); + /* Test for ivars in the superclass (receiver ivar list empty) */ + testIvarsOn([EmptySubFoo new]); + /* Test for ivars in the superclass (receiver ivar list non-empty) */ + testIvarsOn([NonEmptySubFoo new]); + return 0; } diff --git a/ivar.c b/ivar.c index 8504dae..e1053e7 100644 --- a/ivar.c +++ b/ivar.c @@ -154,7 +154,8 @@ typedef enum { ownership ownershipForIvar(Class cls, Ivar ivar) { struct objc_ivar_list *list = cls->ivars; - if ((ivar < list->ivar_list) || (ivar >= &list->ivar_list[list->count])) + if ((list == NULL) || (ivar < list->ivar_list) + || (ivar >= &list->ivar_list[list->count])) { // Try the superclass if (cls->super_class)