Skip to content

Commit 61ba60f

Browse files
author
Greg Parker
committed
[runtime] Fix some casts of _SwiftValue.
* Allow _SwiftValue to be cast to NSObject by yielding the box object itself. * Failed casts from NSDictionary containing _SwiftValue should not crash. SR-4306, rdar://31197066
1 parent 2f0f49e commit 61ba60f

File tree

1 file changed

+19
-5
lines changed

1 file changed

+19
-5
lines changed

stdlib/public/runtime/Casting.cpp

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2195,6 +2195,10 @@ static bool tryDynamicCastBoxedSwiftValue(OpaqueValue *dest,
21952195
const Metadata *srcType,
21962196
const Metadata *targetType,
21972197
DynamicCastFlags flags) {
2198+
// These flag combinations are not handled here.
2199+
assert(!(flags & DynamicCastFlags::Unconditional));
2200+
assert(!(flags & DynamicCastFlags::DestroyOnFailure));
2201+
21982202
// Swift type should be AnyObject or a class type.
21992203
if (!srcType->isAnyClass()) {
22002204
auto existential = dyn_cast<ExistentialTypeMetadata>(srcType);
@@ -2234,7 +2238,8 @@ static bool tryDynamicCastBoxedSwiftValue(OpaqueValue *dest,
22342238

22352239
// Maybe we can cast the boxed value to our destination type somehow.
22362240
auto innerFlags = flags - DynamicCastFlags::TakeOnSuccess
2237-
- DynamicCastFlags::DestroyOnFailure;
2241+
- DynamicCastFlags::DestroyOnFailure
2242+
- DynamicCastFlags::Unconditional;
22382243
if (swift_dynamicCast(dest, const_cast<OpaqueValue*>(boxedValue),
22392244
boxedType, targetType, innerFlags)) {
22402245
// Release the box if we need to.
@@ -2525,10 +2530,19 @@ bool swift::swift_dynamicCast(OpaqueValue *dest, OpaqueValue *src,
25252530
return unwrapResult.success;
25262531

25272532
#if SWIFT_OBJC_INTEROP
2528-
// A class or AnyObject reference may point at a boxed _SwiftValue.
2529-
if (tryDynamicCastBoxedSwiftValue(dest, src, srcType,
2530-
targetType, flags)) {
2531-
return true;
2533+
// A class or AnyObject reference may point to a _SwiftValue box.
2534+
{
2535+
auto innerFlags = flags - DynamicCastFlags::Unconditional
2536+
- DynamicCastFlags::DestroyOnFailure;
2537+
if (tryDynamicCastBoxedSwiftValue(dest, src, srcType,
2538+
targetType, innerFlags)) {
2539+
// TakeOnSuccess was handled inside tryDynamicCastBoxedSwiftValue().
2540+
return true;
2541+
} else {
2542+
// Couldn't cast boxed value to targetType.
2543+
// Fall through and try to cast the _SwiftValue box itself to targetType.
2544+
// (for example, casting _SwiftValue to NSObject will be successful)
2545+
}
25322546
}
25332547
#endif
25342548

0 commit comments

Comments
 (0)