Skip to content

Commit 2508c46

Browse files
committed
Runtime: Fix undersized allocation for out-of-line optional cast result.
We accounted for the size difference between T and T? in the inline case, but not the out-of-line case. rdar://problem/27671131
1 parent b8c66b2 commit 2508c46

File tree

1 file changed

+14
-3
lines changed

1 file changed

+14
-3
lines changed

stdlib/public/runtime/Casting.cpp

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2675,11 +2675,22 @@ static bool _dynamicCastClassToValueViaObjCBridgeable(
26752675
swift_unknownRetain(srcObject);
26762676
}
26772677

2678+
// The extra byte is for the tag.
2679+
auto targetSize = targetType->getValueWitnesses()->size + 1;
2680+
auto targetAlignMask = targetType->getValueWitnesses()->getAlignmentMask();
2681+
26782682
// Object that frees a buffer when it goes out of scope.
26792683
struct FreeBuffer {
26802684
void *Buffer = nullptr;
2681-
~FreeBuffer() { free(Buffer); }
2682-
} freeBuffer;
2685+
size_t size, alignMask;
2686+
FreeBuffer(size_t size, size_t alignMask) :
2687+
size(size), alignMask(alignMask) {}
2688+
2689+
~FreeBuffer() {
2690+
if (Buffer)
2691+
swift_slowDealloc(Buffer, size, alignMask);
2692+
}
2693+
} freeBuffer{targetSize, targetAlignMask};
26832694

26842695
// Allocate a buffer to store the T? returned by bridging.
26852696
// The extra byte is for the tag.
@@ -2691,7 +2702,7 @@ static bool _dynamicCastClassToValueViaObjCBridgeable(
26912702
optDestBuffer = inlineBuffer;
26922703
} else {
26932704
// Allocate a buffer.
2694-
optDestBuffer = malloc(targetType->getValueWitnesses()->size);
2705+
optDestBuffer = swift_slowAlloc(targetSize, targetAlignMask);
26952706
freeBuffer.Buffer = optDestBuffer;
26962707
}
26972708

0 commit comments

Comments
 (0)