Files
swift-mirror/test/SILOptimizer/llvm_arc.sil
Andrew Trick 29b9e51cb6 Remove ReadNone attribute from runtime functions
The Swift compiler incorrectly sets the LLVM "ReadNone" attribute when
declaring swift_getObjCClassFromObject and swift_projectBox. This
means that the LLVM ARC optimizer will hoist ARC "release" operations
above these runtime calls. Since the implementation of the calls reads
the object, this causes a use-after-free crash.

This problem is easy to reproduce with
swift_getObjCClassFromObject. It was only exposed recently because the
SIL optimizer now shrinks object lifetimes, making it easier for LLVM
optimizations to kick in. It is difficult to expose the problem with
swift_projectBox, but the bug/fix is still obvious.

Fixes rdar://73820091: Use-after free application crash.
2021-02-08 14:53:24 -08:00

34 lines
1.3 KiB
Plaintext

// RUN: %target-swift-frontend -O -emit-ir %s | %FileCheck %s
//
// Test LLVM ARC Optimization
// REQUIRES: objc_interop
sil_stage canonical
import Builtin
typealias AnyObject = Builtin.AnyObject
sil @getObject : $@convention(thin) <T where T : AnyObject> () -> T
// Test swift_getObjCClassFromObject side-effects. It reads the object
// argument. A release cannot be hoisted above it.
//
// CHECK-LABEL: define {{.*}}swiftcc %objc_class* @testGetObjCClassFromObjectSideEffect(%swift.type* %T)
// CHECK: entry:
// CHECK-NEXT: %0 = tail call swiftcc %objc_object* @getObject(%swift.type* %T)
// CHECK-NEXT: %.Type = tail call %objc_class* @swift_getObjCClassFromObject(%objc_object* %0)
// CHECK-NEXT: tail call void @swift_unknownObjectRelease(%objc_object* %0)
// CHECK: ret %objc_class* %.Type
// CHECK: }
sil @testGetObjCClassFromObjectSideEffect : $@convention(thin) <T where T : AnyObject> () -> @objc_metatype T.Type {
bb0:
%f = function_ref @getObject : $@convention(thin) <τ_0_0 where τ_0_0 : AnyObject> () -> τ_0_0
%obj = apply %f<T>() : $@convention(thin) <τ_0_0 where τ_0_0 : AnyObject> () -> τ_0_0
%mt = value_metatype $@objc_metatype T.Type, %obj : $T
// Do not hoist this release.
strong_release %obj : $T
return %mt : $@objc_metatype T.Type
}