Skip to content

Instantly share code, notes, and snippets.

@steipete
Last active February 6, 2018 06:14
Show Gist options
  • Save steipete/28525fd7c44a9f16e206 to your computer and use it in GitHub Desktop.
Save steipete/28525fd7c44a9f16e206 to your computer and use it in GitHub Desktop.
Because this is still haunting our customers: https://twitter.com/steipete/status/433355491436011522
BOOL PSPDFSystemFunctionOverriddenInCategory(Class theClass, SEL selector, NSString *__autoreleasing* categoryName) {
NSCParameterAssert(theClass);
NSCParameterAssert(selector);
Dl_info info;
if (dladdr(class_getMethodImplementation(theClass, selector), &info)) {
// /System/Library/Frameworks is a common denominator, some methods are in /usr/lib/libobjc.A.dylib
// Custom app is in /private/var/mobile/Containers/Bundle/Application/<UID>/PSPDFCatalog.app/PSPDFCatalog
if (!strstr(info.dli_fname, "/System/Library") && !strstr(info.dli_fname, "/usr/lib")) {
if (categoryName) *categoryName = @(info.dli_sname);
return YES;
}
}
return NO;
}
void PSPDFCheckAgainstIncompatible3rdPartyCode(void) {
// Is - [NSArray firstObject] overridden?
NSString *categoryName;
if (PSPDFSystemFunctionOverriddenInCategory(NSArray.class, @selector(firstObject), &categoryName)) {
// Test our assumption of the faulty category.
@try { [@[] firstObject]; }
@catch (__unused NSException *exception) {
PSPDFLogError(@"The method `firstObject` of NSArray is overridden in the category %@, which performs differently than Apple's default. Check your categories and 3rd-party code and remove/update the culprit. We're repairing that for now.", categoryName);
// Repair it.
PSPDFSwizzleMethodImplementation(NSArray.class, @selector(firstObject), ^id(NSArray *_self) {
return _self.count ? _self[0] : nil;
});
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment