blob: 232beaaac67d79345d6b6c284bfeefee8f72912a [file] [log] [blame]
// RUN: %target-sil-opt -enable-sil-verify-all -release-hoisting %s | %FileCheck %s
// REQUIRES: CPU=x86_64
// REQUIRES: OS=macosx
sil_stage canonical
import Builtin
import Swift
import SwiftShims
// Test <rdar://59559805> miscompile; use-after-free
// Avoid hoisting strong_release of an existential
// over a store to the value.
protocol ArrayElementProtocol {}
struct ArrayElementStruct : ArrayElementProtocol {
@_hasStorage @_hasInitialValue var dummy: Int { get set }
}
// CHECK-LABEL: sil @testArrayStorageInitAfterFree : $@convention(thin) () -> () {
// CHECK: [[ARRAY:%.*]] = alloc_ref [stack] [tail_elems $ArrayElementProtocol * undef : $Builtin.Word] $_ContiguousArrayStorage<ArrayElementProtocol>
// CHECK: [[CAST:%.*]] = upcast [[ARRAY]] : $_ContiguousArrayStorage<ArrayElementProtocol> to $__ContiguousArrayStorageBase
// CHECK: [[TAIL:%.*]] = ref_tail_addr [[CAST]] : $__ContiguousArrayStorageBase, $ArrayElementProtocol
// CHECK: [[ADR:%.*]] = init_existential_addr [[TAIL]] : $*ArrayElementProtocol, $ArrayElementStruct
// CHECK: store %{{.*}} to [[ADR]] : $*ArrayElementStruct
// CHECK: strong_release [[ARRAY]] : $_ContiguousArrayStorage<ArrayElementProtocol>
// CHECK-LABEL: } // end sil function 'testArrayStorageInitAfterFree'
sil @testArrayStorageInitAfterFree : $@convention(thin) () -> () {
bb0:
%0 = alloc_ref [stack] [tail_elems $ArrayElementProtocol * undef : $Builtin.Word] $_ContiguousArrayStorage<ArrayElementProtocol>
%1 = upcast %0 : $_ContiguousArrayStorage<ArrayElementProtocol> to $__ContiguousArrayStorageBase
%2 = struct $_SwiftArrayBodyStorage (undef : $Int, undef : $UInt)
%3 = struct $_ArrayBody (%2 : $_SwiftArrayBodyStorage)
%4 = ref_element_addr %1 : $__ContiguousArrayStorageBase, #__ContiguousArrayStorageBase.countAndCapacity
store %3 to %4 : $*_ArrayBody
%6 = ref_tail_addr %1 : $__ContiguousArrayStorageBase, $ArrayElementProtocol
%7 = value_to_bridge_object undef : $Builtin.Int64
%8 = struct $_StringObject (undef : $UInt64, %7 : $Builtin.BridgeObject)
%9 = struct $_StringGuts (%8 : $_StringObject)
%10 = struct $String (%9 : $_StringGuts)
%11 = struct $ArrayElementStruct (undef : $Int)
%12 = init_existential_addr %6 : $*ArrayElementProtocol, $ArrayElementStruct
store %11 to %12 : $*ArrayElementStruct
strong_release %0 : $_ContiguousArrayStorage<ArrayElementProtocol>
dealloc_ref [stack] %0 : $_ContiguousArrayStorage<ArrayElementProtocol>
%16 = tuple ()
return %16 : $()
}