Chaitanya Gupta
Chaitanya Gupta

Reputation: 4053

How do I find out if a superclass private method is overridden in Objective-C?

Since, in Objective-C, private methods are not really private (the method dispatch mechanism doesn't distinguish between private v/s public methods), it is really easy for a subclass to override private methods of a superclass (more on this at Cocoa Coding Guidelines).

However, it is not so easy to detect this. I am looking for a readymade tool that can help me with this.

This cannot simply be a static analysis tool because private methods are not exposed in the interface. This tool will either have to examine the binaries or figure this out at runtime. According to me, this tool will have to do something similar to the following:

  1. Get a list of all the public methods of every class used by the project by examining the headers, then perform either step 2 or step 3

  2. Get the overridden private methods by examining the binaries

    a) Read the app binary + all the dynamic libraries it links against to get a list of all the methods defined by every class used by the app.

    b) Of these, methods not found in step 1 are private methods.

    c) Go through the class hierarchy and figure out subclasses that override private methods of superclasses

  3. Get the overridden private methods at runtime

    a) Run the app

    b) Using the Objective-C runtime methods, we can get all methods defined for all the classes.

    c) Again, methods not found in step 1 are private methods

    d) Go through the class hierarchy and figure out subclasses that override private methods of superclasses

This will not always work -- since classes and methods can be added/removed at runtime, some cases will get missed (most notably, NSManagedObject subclasses, where methods for Core Data properties are provided at runtime). That's okay though, I am willing to live with this limitation.

I believe its very much possible to achieve this using libclang, object file inspection tools like otoolor nm, and the Objective-C runtime, but is there a readymade tool that does all this?

Note: I am not looking for ways to mitigate this issue; just how to detect this condition.

Upvotes: 4

Views: 381

Answers (1)

pfandrade
pfandrade

Reputation: 2419

You can do this by tapping into the Objective-C runtime.

See objc/runtime.h, namely:

/** 
 * Describes the instance methods implemented by a class.
 * 
 * @param cls The class you want to inspect.
 * @param outCount On return, contains the length of the returned array. 
 *  If outCount is NULL, the length is not returned.
 * 
 * @return An array of pointers of type Method describing the instance methods 
 *  implemented by the class—any instance methods implemented by superclasses are not included. 
 *  The array contains *outCount pointers followed by a NULL terminator. You must free the array with free().
 * 
 *  If cls implements no instance methods, or cls is Nil, returns NULL and *outCount is 0.
 * 
 * @note To get the class methods of a class, use \c class_copyMethodList(object_getClass(cls), &count).
 * @note To get the implementations of methods that may be implemented by superclasses, 
 *  use \c class_getInstanceMethod or \c class_getClassMethod.
 */
OBJC_EXPORT Method *class_copyMethodList(Class cls, unsigned int *outCount) 
     __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);

Upvotes: 1

Related Questions