Fixed ivar offset checking to take account for alignment.

main
theraven 16 years ago
parent 6a94efd4cf
commit 9dc0343c21

@ -756,38 +756,51 @@ __objc_compute_ivar_offsets (Class class)
}
else
{
if (class->ivars != 0)
if (NULL == class->ivars)
{
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,
"Offset of first instance variable, %s, is %d",
class->ivars->ivar_list[0].ivar_name, start);
fprintf(stderr,
"Last instance variable in superclass, %s, ends at offset %d",
ivar->ivar_name,
ivar->ivar_offset + objc_sizeof_type(ivar->ivar_type));
fprintf(stderr, "This probably means that you are subclassing a class from a library, which has changed in a binary-incompatible way.\n");
abort();
}
}
return;
}
Class super = class_superclass_of_class(class);
int start = class->ivars->ivar_list[0].ivar_offset;
/* Quick and dirty test. If the first ivar comes straight after the last
* class, then it's fine. */
if (Nil == super || start == super->instance_size)
{
return;
}
/* Find the last superclass with at least one ivar. */
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)))
{
return;
}
/* The classes don't line up, but don't panic; check that the
* difference is not just padding for alignment */
int align = objc_alignof_type(class->ivars->ivar_list[0].ivar_type);
if (start > ivar->ivar_offset &&
start - ivar->ivar_offset < align)
{
return;
}
/* 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,
"Offset of first instance variable, %s, is %d",
class->ivars->ivar_list[0].ivar_name, start);
fprintf(stderr,
"Last instance variable in superclass, %s, ends at offset %d",
ivar->ivar_name,
ivar->ivar_offset + objc_sizeof_type(ivar->ivar_type));
fprintf(stderr, "This probably means that you are subclassing a class from a library, which has changed in a binary-incompatible way.\n");
abort();
}
}

Loading…
Cancel
Save