[Runtime] Accept Nil in the patched bundleForClass:.

The patched +[NSBundle bundleForClass:] crashes on Nil, while the original Foundation implementation returns the main bundle. Avoid the crash and pass Nil through to Foundation. This also ensures that Nil is passed through to class_getImageName rather than crashing.

SR-9188 rdar://problem/45849924
This commit is contained in:
Mike Ash
2018-11-06 15:20:18 -05:00
parent 51198e40b1
commit bdb822a788
2 changed files with 29 additions and 1 deletions

View File

@@ -56,8 +56,11 @@ static objc_hook_getImageName defaultGetImageNameFromClass = nullptr;
/// Get the image name corresponding to a Swift class, accounting for
/// dynamically-initialized class metadata. Returns NO for ObjC classes.
static BOOL
getImageNameFromSwiftClass(Class _Nonnull objcClass,
getImageNameFromSwiftClass(Class _Nullable objcClass,
const char * _Nullable * _Nonnull outImageName) {
if (objcClass == Nil)
return NO;
auto *classAsMetadata = reinterpret_cast<const ClassMetadata *>(objcClass);
// Is this a Swift class?

25
test/stdlib/Bundle.swift Normal file
View File

@@ -0,0 +1,25 @@
// RUN: %target-run-simple-swift
// REQUIRES: executable_test
// REQUIRES: objc_interop
import Foundation
import StdlibUnittest
var BundleTests = TestSuite("BundleTests")
BundleTests.test("Bundle.bundleForNilClass") {
// Ensure that bundleForClass: tolerates a nil parameter. The
// Foundation implementation does. The patched version from
// ObjCRuntimeGetImageNameFromClass did not.
//
// SR-9188
typealias BundleForClassFunc =
@convention(c) (AnyObject, Selector, AnyObject?) -> Bundle
let sel = #selector(Bundle.init(for:))
let imp = unsafeBitCast(Bundle.method(for: sel), to: BundleForClassFunc.self)
let bundleForNil = imp(Bundle.self, sel, nil);
expectEqual(Bundle.main, bundleForNil)
}
runAllTests()