Skip to content

[4.2][Runtime][Foundation] Supplement the class_getImageName patch with a patch to +[NSBundle bundleForClass:] on older "embedded" targets #19413

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Sep 20, 2018

Conversation

mikeash
Copy link
Contributor

@mikeash mikeash commented Sep 20, 2018

Cherry-pick #19389 to 4.2.

rdar://problem/44489216

jrose-apple and others added 2 commits September 20, 2018 09:35
'const T *' isn't compatible with a function pointer, so upstream
Clang complained about the 'patch_t' convenience constructor we were
using. It's not like we need general functionality or convenience
here, so just pass the members of the patch_t type separately and
without any templating, and drop it entirely.

No functionality change.
…patch to +[NSBundle bundleForClass:] on older "embedded" targets. The patch technique of editing the symbol table doesn't work for +bundleForClass:'s call to class_getImageName when +bundleForClass: is in an embedded shared cache.

rdar://problem/44489216
@mikeash
Copy link
Contributor Author

mikeash commented Sep 20, 2018

@swift-ci please test

@mikeash
Copy link
Contributor Author

mikeash commented Sep 20, 2018

@swift-ci please nominate

Explanation: Swift 4.2 needs a hook for ObjC's class_getImageName so that APIs like +[NSBundle bundleForClass:] work correctly. On older OSes where the hook is not available, a patch is installed by editing the symbol lookups in loaded libraries. It turns out that patch technique does not work on iOS devices for calls within the dyld shared cache. This change swizzles +[NSBundle bundleForClass:] to patch in the Swift-specific lookup.
Scope of Issue: Using Bundle(for:) on a class in a framework will incorrectly return the main bundle if the class has been dynamically allocated. A common example of this is a UIViewController with generic ancestry.
Origination: The problem with Bundle(for:) not working on certain Swift classes has been around for a long time. This bug was filed in 2016: https://bugs.swift.org/browse/SR-1917. However, Swift 4.2 does a lot more class initialization at runtime, which makes this problem happen in many more cases compared to older versions.
Risk: Low. Unfortunately the version that doesn't work on iOS made it into the release, so the broken behavior is already out there. This change probably won't make things any worse. The replacement for +[NSBundle bundleForClass:] immediately calls through to the original implementation for non-Swift classes so there is no change in behavior for any classes in the frameworks.
Reviewed by: Jordan Rose, Tony Parker
Testing: The Swift test suite was run locally and in CI. An example app which triggers the bug was successfully launched on iOS 11.4.1 and iOS 12, with single-stepping through the patch to ensure everything was behaving as it was supposed to.

@mikeash mikeash merged commit 55f273a into swiftlang:swift-4.2-branch Sep 20, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants