Add lots of checks for NULL-pointer arguments to runtime functions.

main
theraven 15 years ago
parent caa4a7253c
commit 91e9758fda

@ -19,6 +19,7 @@
#include <assert.h> #include <assert.h>
struct objc_slot *objc_get_slot(Class cls, SEL selector); struct objc_slot *objc_get_slot(Class cls, SEL selector);
#define CHECK_ARG(arg) if (0 == arg) { return 0; }
/** /**
* Looks up the instance method in a specific class, without recursing into * Looks up the instance method in a specific class, without recursing into
@ -59,6 +60,9 @@ static void objc_updateDtableForClassContainingMethod(Method m)
BOOL class_addIvar(Class cls, const char *name, size_t size, uint8_t alignment, BOOL class_addIvar(Class cls, const char *name, size_t size, uint8_t alignment,
const char *types) const char *types)
{ {
CHECK_ARG(cls);
CHECK_ARG(name);
CHECK_ARG(types);
// You can't add ivars to initialized classes. Note: We can't use the // You can't add ivars to initialized classes. Note: We can't use the
// resolved flag here because class_getInstanceVariable() sets it. // resolved flag here because class_getInstanceVariable() sets it.
if (objc_test_class_flag(cls, objc_class_flag_initialized)) if (objc_test_class_flag(cls, objc_class_flag_initialized))
@ -105,6 +109,10 @@ BOOL class_addIvar(Class cls, const char *name, size_t size, uint8_t alignment,
BOOL class_addMethod(Class cls, SEL name, IMP imp, const char *types) BOOL class_addMethod(Class cls, SEL name, IMP imp, const char *types)
{ {
CHECK_ARG(cls);
CHECK_ARG(name);
CHECK_ARG(imp);
CHECK_ARG(types);
const char *methodName = sel_getName(name); const char *methodName = sel_getName(name);
struct objc_method_list *methods; struct objc_method_list *methods;
for (methods=cls->methods; methods!=NULL ; methods=methods->next) for (methods=cls->methods; methods!=NULL ; methods=methods->next)
@ -138,6 +146,8 @@ BOOL class_addMethod(Class cls, SEL name, IMP imp, const char *types)
BOOL class_addProtocol(Class cls, Protocol *protocol) BOOL class_addProtocol(Class cls, Protocol *protocol)
{ {
CHECK_ARG(cls);
CHECK_ARG(protocol);
if (class_conformsToProtocol(cls, protocol)) { return NO; } if (class_conformsToProtocol(cls, protocol)) { return NO; }
struct objc_protocol_list *protocols = struct objc_protocol_list *protocols =
malloc(sizeof(struct objc_protocol_list)); malloc(sizeof(struct objc_protocol_list));
@ -149,119 +159,120 @@ BOOL class_addProtocol(Class cls, Protocol *protocol)
return YES; return YES;
} }
Ivar *
class_copyIvarList(Class cls, unsigned int *outCount) Ivar * class_copyIvarList(Class cls, unsigned int *outCount)
{ {
struct objc_ivar_list *ivarlist = NULL; CHECK_ARG(cls);
unsigned int count = 0; struct objc_ivar_list *ivarlist = NULL;
unsigned int index; unsigned int count = 0;
Ivar *list; unsigned int index;
Ivar *list;
if (Nil != cls)
{ if (Nil != cls)
ivarlist = cls->ivars; {
} ivarlist = cls->ivars;
if (ivarlist != NULL) }
{ if (ivarlist != NULL)
count = ivarlist->count; {
} count = ivarlist->count;
if (outCount != NULL) }
{ if (outCount != NULL)
*outCount = count; {
} *outCount = count;
if (count == 0) }
{ if (count == 0)
return NULL; {
} return NULL;
}
list = malloc((count + 1) * sizeof(struct objc_ivar *));
list[count] = NULL; list = malloc((count + 1) * sizeof(struct objc_ivar *));
count = 0; list[count] = NULL;
for (index = 0; index < ivarlist->count; index++) count = 0;
{ for (index = 0; index < ivarlist->count; index++)
list[count++] = &ivarlist->ivar_list[index]; {
} list[count++] = &ivarlist->ivar_list[index];
}
return list;
} return list;
}
Method *
class_copyMethodList(Class cls, unsigned int *outCount) Method * class_copyMethodList(Class cls, unsigned int *outCount)
{ {
unsigned int count = 0; CHECK_ARG(cls);
Method *list; unsigned int count = 0;
struct objc_method_list *methods; Method *list;
struct objc_method_list *methods;
if (cls != NULL)
{ if (cls != NULL)
for (methods = cls->methods; methods != NULL; methods = methods->next) {
{ for (methods = cls->methods; methods != NULL; methods = methods->next)
count += methods->count; {
} count += methods->count;
} }
if (outCount != NULL) }
{ if (outCount != NULL)
*outCount = count; {
} *outCount = count;
if (count == 0) }
{ if (count == 0)
return NULL; {
} return NULL;
}
list = malloc((count + 1) * sizeof(struct objc_method *));
list[count] = NULL; list = malloc((count + 1) * sizeof(struct objc_method *));
count = 0; list[count] = NULL;
for (methods = cls->methods; methods != NULL; methods = methods->next) count = 0;
{ for (methods = cls->methods; methods != NULL; methods = methods->next)
unsigned int index; {
unsigned int index;
for (index = 0; index < methods->count; index++) for (index = 0; index < methods->count; index++)
{ {
list[count++] = &methods->methods[index]; list[count++] = &methods->methods[index];
} }
} }
return list; return list;
} }
Protocol ** Protocol** class_copyProtocolList(Class cls, unsigned int *outCount)
class_copyProtocolList(Class cls, unsigned int *outCount) {
{ CHECK_ARG(cls);
struct objc_protocol_list *protocolList = NULL; struct objc_protocol_list *protocolList = NULL;
struct objc_protocol_list *list; struct objc_protocol_list *list;
unsigned int count = 0; unsigned int count = 0;
Protocol **protocols; Protocol **protocols;
if (Nil != cls) if (Nil != cls)
{ {
protocolList = cls->protocols; protocolList = cls->protocols;
} }
for (list = protocolList; list != NULL; list = list->next) for (list = protocolList; list != NULL; list = list->next)
{ {
count += list->count; count += list->count;
} }
if (outCount != NULL) if (outCount != NULL)
{ {
*outCount = count; *outCount = count;
} }
if (count == 0) if (count == 0)
{ {
return NULL; return NULL;
} }
protocols = malloc((count + 1) * sizeof(Protocol *)); protocols = malloc((count + 1) * sizeof(Protocol *));
protocols[count] = NULL; protocols[count] = NULL;
count = 0; count = 0;
for (list = protocolList; list != NULL; list = list->next) for (list = protocolList; list != NULL; list = list->next)
{ {
memcpy(&protocols[count], list->list, list->count * sizeof(Protocol *)); memcpy(&protocols[count], list->list, list->count * sizeof(Protocol *));
count += list->count; count += list->count;
} }
return protocols; return protocols;
} }
id class_createInstance(Class cls, size_t extraBytes) id class_createInstance(Class cls, size_t extraBytes)
{ {
CHECK_ARG(cls);
if (Nil == cls) { return nil; } if (Nil == cls) { return nil; }
id obj = malloc(cls->instance_size + extraBytes); id obj = malloc(cls->instance_size + extraBytes);
obj->isa = cls; obj->isa = cls;
@ -270,6 +281,8 @@ id class_createInstance(Class cls, size_t extraBytes)
Method class_getInstanceMethod(Class aClass, SEL aSelector) Method class_getInstanceMethod(Class aClass, SEL aSelector)
{ {
CHECK_ARG(aClass);
CHECK_ARG(aSelector);
// Do a dtable lookup to find out which class the method comes from. // Do a dtable lookup to find out which class the method comes from.
struct objc_slot *slot = objc_get_slot(aClass, aSelector); struct objc_slot *slot = objc_get_slot(aClass, aSelector);
if (NULL == slot) { return NULL; } if (NULL == slot) { return NULL; }
@ -288,8 +301,8 @@ Method class_getClassMethod(Class aClass, SEL aSelector)
Ivar class_getClassVariable(Class cls, const char* name) Ivar class_getClassVariable(Class cls, const char* name)
{ {
assert(0 && "Class variables not implemented"); // Note: We don't have compiler support for cvars in ObjC
return NULL; return class_getInstanceVariable(object_getClass((id)cls), name);
} }
size_t class_getInstanceSize(Class cls) size_t class_getInstanceSize(Class cls)
@ -298,8 +311,7 @@ size_t class_getInstanceSize(Class cls)
return cls->instance_size; return cls->instance_size;
} }
Ivar Ivar class_getInstanceVariable(Class cls, const char *name)
class_getInstanceVariable(Class cls, const char *name)
{ {
if (name != NULL) if (name != NULL)
{ {
@ -328,31 +340,35 @@ class_getInstanceVariable(Class cls, const char *name)
// conjunction with class_setIvarLayout(). // conjunction with class_setIvarLayout().
const char *class_getIvarLayout(Class cls) const char *class_getIvarLayout(Class cls)
{ {
if (Nil == cls) { return NULL; } CHECK_ARG(cls);
return (char*)cls->ivars; return (char*)cls->ivars;
} }
IMP class_getMethodImplementation(Class cls, SEL name) IMP class_getMethodImplementation(Class cls, SEL name)
{ {
CHECK_ARG(cls);
CHECK_ARG(name);
struct objc_object obj = { cls }; struct objc_object obj = { cls };
return (IMP)objc_msg_lookup((id)&obj, name); return (IMP)objc_msg_lookup((id)&obj, name);
} }
IMP class_getMethodImplementation_stret(Class cls, SEL name) IMP class_getMethodImplementation_stret(Class cls, SEL name)
{ {
CHECK_ARG(cls);
CHECK_ARG(name);
struct objc_object obj = { cls }; struct objc_object obj = { cls };
return (IMP)objc_msg_lookup((id)&obj, name); return (IMP)objc_msg_lookup((id)&obj, name);
} }
const char * class_getName(Class cls) const char * class_getName(Class cls)
{ {
if (Nil == cls) { return "nil"; } CHECK_ARG(cls);
return cls->name; return cls->name;
} }
int class_getVersion(Class theClass) int class_getVersion(Class theClass)
{ {
if (Nil == theClass) { return 0; } CHECK_ARG(theClass);
return theClass->version; return theClass->version;
} }
@ -364,7 +380,7 @@ const char *class_getWeakIvarLayout(Class cls)
BOOL class_isMetaClass(Class cls) BOOL class_isMetaClass(Class cls)
{ {
if (Nil == cls) { return NO; } CHECK_ARG(cls);
return objc_test_class_flag(cls, objc_class_flag_meta); return objc_test_class_flag(cls, objc_class_flag_meta);
} }
@ -392,7 +408,7 @@ IMP class_replaceMethod(Class cls, SEL name, IMP imp, const char *types)
void class_setIvarLayout(Class cls, const char *layout) void class_setIvarLayout(Class cls, const char *layout)
{ {
if (Nil == cls) { return; } if ((Nil == cls) || (NULL == layout)) { return; }
struct objc_ivar_list *list = (struct objc_ivar_list*)layout; struct objc_ivar_list *list = (struct objc_ivar_list*)layout;
size_t listsize = sizeof(struct objc_ivar_list) + size_t listsize = sizeof(struct objc_ivar_list) +
sizeof(struct objc_ivar) * (list->count - 1); sizeof(struct objc_ivar) * (list->count - 1);
@ -403,6 +419,8 @@ void class_setIvarLayout(Class cls, const char *layout)
__attribute__((deprecated)) __attribute__((deprecated))
Class class_setSuperclass(Class cls, Class newSuper) Class class_setSuperclass(Class cls, Class newSuper)
{ {
CHECK_ARG(cls);
CHECK_ARG(newSuper);
if (Nil == cls) { return Nil; } if (Nil == cls) { return Nil; }
Class oldSuper = cls->super_class; Class oldSuper = cls->super_class;
cls->super_class = newSuper; cls->super_class = newSuper;
@ -422,19 +440,19 @@ void class_setWeakIvarLayout(Class cls, const char *layout)
const char * ivar_getName(Ivar ivar) const char * ivar_getName(Ivar ivar)
{ {
if (NULL == ivar) { return NULL; } CHECK_ARG(ivar);
return ivar->name; return ivar->name;
} }
ptrdiff_t ivar_getOffset(Ivar ivar) ptrdiff_t ivar_getOffset(Ivar ivar)
{ {
if (NULL == ivar) { return 0; } CHECK_ARG(ivar);
return ivar->offset; return ivar->offset;
} }
const char * ivar_getTypeEncoding(Ivar ivar) const char * ivar_getTypeEncoding(Ivar ivar)
{ {
if (NULL == ivar) { return NULL; } CHECK_ARG(ivar);
return ivar->type; return ivar->type;
} }
@ -473,6 +491,7 @@ IMP method_setImplementation(Method method, IMP imp)
id objc_getRequiredClass(const char *name) id objc_getRequiredClass(const char *name)
{ {
CHECK_ARG(name);
id cls = objc_getClass(name); id cls = objc_getClass(name);
if (nil == cls) if (nil == cls)
{ {
@ -537,6 +556,7 @@ static inline void safe_remove_from_subclass_list(Class cls)
void objc_disposeClassPair(Class cls) void objc_disposeClassPair(Class cls)
{ {
if (0 == cls) { return; }
Class meta = ((id)cls)->isa; Class meta = ((id)cls)->isa;
// Remove from the runtime system so nothing tries updating the dtable // Remove from the runtime system so nothing tries updating the dtable
// while we are freeing the class. // while we are freeing the class.
@ -595,44 +615,32 @@ Class objc_allocateClassPair(Class superclass, const char *name, size_t extraByt
void *object_getIndexedIvars(id obj) void *object_getIndexedIvars(id obj)
{ {
if (nil == obj) { return NULL; } CHECK_ARG(obj);
/*
if (class_isMetaClass(obj->isa))
{
return ((char*)obj) + sizeof(struct objc_class);
}
*/
return ((char*)obj) + obj->isa->instance_size; return ((char*)obj) + obj->isa->instance_size;
} }
Class object_getClass(id obj) Class object_getClass(id obj)
{ {
if (nil != obj) CHECK_ARG(obj);
Class isa = obj->isa;
while ((Nil != isa) && objc_test_class_flag(isa, objc_class_flag_hidden_class))
{ {
Class isa = obj->isa; isa = isa->super_class;
while ((Nil != isa) && objc_test_class_flag(isa, objc_class_flag_hidden_class))
{
isa = isa->super_class;
}
return isa;
} }
return Nil; return isa;
} }
Class object_setClass(id obj, Class cls) Class object_setClass(id obj, Class cls)
{ {
if (nil != obj) CHECK_ARG(obj);
{ Class oldClass = obj->isa;
Class oldClass = obj->isa; obj->isa = cls;
obj->isa = cls; return oldClass;
return oldClass;
}
return Nil;
} }
const char *object_getClassName(id obj) const char *object_getClassName(id obj)
{ {
if (nil == obj) { return "nil"; } CHECK_ARG(obj);
return class_getName(object_getClass(obj)); return class_getName(object_getClass(obj));
} }

Loading…
Cancel
Save