From bd73cc4e57029493873e62fc43c3c2ecc2e88cb0 Mon Sep 17 00:00:00 2001 From: theraven Date: Sun, 15 Nov 2009 02:28:45 +0000 Subject: [PATCH] Added run-time abort if the first ivar of a newly-loaded class does not immediately follow on from the previous one. This (hopefully, modulo some potential weirdness related to bitfields) means that we should now get programs refusing to start in most cases where they depend on frameworks that had their ABI change but didn't bump the library version. This seems preferable to the previous behaviour of corrupting memory (note that this won't catch the case where the superclass has its ivars rearranged, but remains exactly the same size and the subclass references the ivars). --- init.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/init.c b/init.c index 8efb899..f0970c5 100644 --- a/init.c +++ b/init.c @@ -24,7 +24,9 @@ a copy of the GCC Runtime Library Exception along with this program; see the files COPYING3 and COPYING.RUNTIME respectively. If not, see . */ +#include #include "objc/runtime-legacy.h" +#include "objc/encoding.h" #include "lock.h" /* The version number of this runtime. This must match the number @@ -749,6 +751,33 @@ __objc_compute_ivar_offsets (Class class) } } } + else + { + if (class->ivars != 0) + { + Class super = class_superclass_of_class(class); + int start = class->ivars->ivar_list[0].ivar_offset; + /* Quick and dirty test */ + if (Nil != super && start != super->instance_size) + { + while (NULL == super->ivars) + { + super = class_superclass_of_class(super); + } + struct objc_ivar *ivar = + &super->ivars->ivar_list[super->ivars->ivar_count-1]; + if (start != (ivar->ivar_offset + objc_sizeof_type(ivar->ivar_type))) + { + /* Panic if this class has an instance variable that overlaps the + * superclass. */ + fprintf(stderr, "Error: Instance variables in %s overlap superclass %s", + class->name, super->name); + fprintf(stderr, "This probably means that you are subclassing a class from a library, which has changed in a binary-incompatible way.\n"); + abort(); + } + } + } + } } static void