Saturday, February 29, 2020

The Technical Backstory of Retroactive


The stack trace is fascinating. It looks like some sort of access violation when initializing a font. We are going to fix this by swizzling Aperture.

0 com.apple.CoreText 0x00007fff3c6a2019 CTFontGetClientObject + 13
1 com.apple.UIFoundation 0x00007fff6b37bcfc __UIFontGetExtraData + 18
2 com.apple.UIFoundation 0x00007fff6b37cd67 -[NSFont initWithTypefaceInfo:key:renderingMode:] + 47
3 com.apple.prokit 0x0000000106955159 +[NSProFont _proSystemFontWithFontName:pointSize:fontAppearance:useSystemHelveticaAdjustments:] + 736
4 com.apple.prokit 0x00000001069b553e -[NSCell(ProAppearanceExtensions) proSetFont:] + 155
5 com.apple.AppKit 0x00007fff37a4bc03 -[NSTextFieldCell setFont:] + 47
6 com.apple.Aperture3 0x0000000105f14cc2 0x105c9e000 + 2583746
7 com.apple.AppKit 0x00007fff37a9dec7 -[NSTextFieldCell init] + 31
8 com.apple.Aperture3 0x0000000105f12901 0x105c9e000 + 2574593
9 com.apple.Aperture3 0x0000000105f22bf4 0x105c9e000 + 2640884
10 com.apple.Aperture3 0x0000000105f1636d 0x105c9e000 + 2589549
11 com.apple.AppKit 0x00007fff379fdb02 -[NSIBObjectData nibInstantiateWithOwner:options:topLevelObjects:] + 1540
12 com.apple.AppKit 0x00007fff37b66b37 -[NSNib _instantiateNibWithExternalNameTable:options:] + 647
13 com.apple.AppKit 0x00007fff37b667bb -[NSNib _instantiateWithOwner:options:topLevelObjects:] + 143
14 com.apple.AppKit 0x00007fff37b65b08 -[NSViewController loadView] + 345
15 com.apple.AppKit 0x00007fff37b61b88 -[NSViewController _loadViewIfRequired] + 72
16 com.apple.AppKit 0x00007fff37b61b05 -[NSViewController view] + 23
17 com.apple.Aperture3 0x0000000105cf30ed 0x105c9e000 + 348397
18 com.apple.AppKit 0x00007fff37b601e0 -[NSWindowController _windowDidLoad] + 624
19 com.apple.AppKit 0x00007fff37ad3718 -[NSWindowController window] + 110

Step 4. Create a new framework in Xcode to swizzle broken methods in Aperture, and fill in selectors that have been removed.

It’s swizzle time! How do we swizzle an existing app? Of course, we use Xcode.

If you don’t have Xcode yet, download Xcode, then create a new Xcode project with a macOS Framework template.

Make sure the language is Objective-C.

Create a new file.

Create an Objective-C file.

The easiest way to swizzle something is just to make a category on NSObject and call method_exchangeImplementations in +load. I’ll name this file “Swizzling”, but you can name it whatever you want.

If we want to swizzle the problematic initializer on NSProFont, it’s time to put on our (NS)Hipster hat and revise our swizzling skills.

Import the Objective-C runtime header, and let the fun begin.

import <objc/runtime.h>

Refer back to the problem report. Here’s the suspect of the crash:

3 com.apple.prokit 0x0000000106955159 +[NSProFont _proSystemFontWithFontName:pointSize:fontAppearance:useSystemHelveticaAdjustments:] + 736

Start with the most obvious idea: what if we just initialize a regular system font instead of whatever special pro font Aperture is trying (and failing) to initialize?

+ (NSFont *)swizzled_proSystemFontWithFontName:(NSString *)name pointSize:(CGFloat)size fontAppearance:(id)appearance useSystemHelveticaAdjustments:(BOOL)adjustments {
return [NSFont systemFontOfSize:size];
}

Then use the dynamic Objective-C runtime to exchange Aperture’s implementation with ours.

+ (void)load {
method_exchangeImplementations(class_getClassMethod(NSClassFromString(@"NSProFont"), NSSelectorFromString(@"_proSystemFontWithFontName:pointSize:fontAppearance:useSystemHelveticaAdjustments:")), class_getClassMethod([self class], @selector(swizzled_proSystemFontWithFontName:pointSize:fontAppearance:useSystemHelveticaAdjustments:)));
}

Some wishful thinking: If initializing the font doesn’t fail, this can probably get us over to the next step.



from Hacker News https://ift.tt/2JvAkZJ

No comments:

Post a Comment

Note: Only a member of this blog may post a comment.