#import <malloc/malloc.h>
#import <objc/runtime.h>
static sigjmp_buf sigjmp_env;
void PointerReadFailedHandler(int signum)
{
siglongjmp (sigjmp_env, 1);
}
BOOL IsPointerAnObject(const void *testPointer, BOOL *allocatedLargeEnough)
{
*allocatedLargeEnough = NO;
// Set up SIGSEGV and SIGBUS handlers
struct sigaction new_segv_action, old_segv_action;
struct sigaction new_bus_action, old_bus_action;
new_segv_action.sa_handler = PointerReadFailedHandler;
new_bus_action.sa_handler = PointerReadFailedHandler;
sigemptyset(&new_segv_action.sa_mask);
sigemptyset(&new_bus_action.sa_mask);
new_segv_action.sa_flags = 0;
new_bus_action.sa_flags = 0;
sigaction (SIGSEGV, &new_segv_action, &old_segv_action);
sigaction (SIGBUS, &new_bus_action, &old_bus_action);
// The signal handler will return us to here if a signal is raised
if (sigsetjmp(sigjmp_env, 1))
{
sigaction (SIGSEGV, &old_segv_action, NULL);
sigaction (SIGBUS, &old_bus_action, NULL);
return NO;
}
Class testPointerClass = *((Class *)testPointer);
// Get the list of classes and look for testPointerClass
BOOL isClass = NO;
NSInteger numClasses = objc_getClassList(NULL, 0);
Class *classesList = malloc(sizeof(Class) * numClasses);
numClasses = objc_getClassList(classesList, numClasses);
for (int i = 0; i < numClasses; i++)
{
if (classesList[i] == testPointerClass)
{
isClass = YES;
break;
}
}
free(classesList);
// We're done with the signal handlers (install the previous ones)
sigaction (SIGSEGV, &old_segv_action, NULL);
sigaction (SIGBUS, &old_bus_action, NULL);
// Pointer does not point to a valid isa pointer
if (!isClass)
{
return NO;
}
// Check the allocation size
size_t allocated_size = malloc_size(testPointer);
size_t instance_size = class_getInstanceSize(testPointerClass);
if (allocated_size > instance_size)
{
*allocatedLargeEnough = YES;
}
return YES;
}