In a UIViewController (rolePageController) I configure another UIViewController (drawerController) and pass it 2 UIViews from the role page that will be part of the drawerController's configuration. As soon as the drawerController tries to access the IBOutlet views from the rolePageController, it crashes with EXC_BAD_ACCESS (code=EXC_I386_GPFLT).
In the 1st VC (rolePageController), here are the IBOutlets:
@IBOutlet var rolePageDrawerView: UIView!
@IBOutlet var rolePageContentView: UIView!
In rolePageController.viewDidLoad() I make a call to the drawerController.configureDrawer(...):
override func viewDidLoad() {
super.viewDidLoad()
//other stuff happens here
let drawerController = UIStoryboard(name: "StoryboardName", bundle: nil).instantiateViewController(withIdentifier: "drawerController") as! DrawerViewController
drawerController.configureDrawer(drawerContainerView: self.rolePageDrawerView, overlaidView: self.rolePageContentView)
//other stuff here
}
The DrawerViewController protocol is defined as:
protocol DrawerViewController where Self: UIViewController {
func configureDrawer(drawerContainerView: UIView, overlaidView: UIView)
}
Here is the code for the configureDrawer(...) func:
private var drawerParentView: UIView!
private var overlaidByDrawerView: UIView!
func configureDrawer(drawerContainerView: UIView, overlaidView: UIView) {
self.drawerParentView = drawerContainerView
self.overlaidByDrawerView = overlaidView
}
Noticed in the debugger that the drawerController instance that is called does not match the self instance that receives the call. Here is the address of the instance that will be called:
Here is the address of the instance when I step into the call:
The address of drawerController before the call is not the address of self when I step into the call. That should never happen.
I have created a simplified project that reproduces the crash at https://github.com/ksoftllc/DynamicStackBufferOverflow.
Solution Solution turned out to be to remove the where clause from the DrawerViewController protocol.
protocol DrawerViewController where Self: UIViewController {
func configureDrawer(drawerContainerView: UIView, overlaidView: UIView)
}
Found the offending code, but I don't know why this would cause the errors I was seeing. The drawerController conforms to DrawerViewController protocol, defined as:
protocol DrawerViewController where Self: UIViewController {
func configureDrawer(drawerContainerView: UIView, overlaidView: UIView)
}
When I remove the Where condition, it no longer crashes.
protocol DrawerViewController {
func configureDrawer(drawerContainerView: UIView, overlaidView: UIView)
}
The where clause was not actually necessary for correct function of the program, so I will proceed without it.
UPDATE I filed a bug with swift.org and received a response. Adding a where clause to a protocol is not supported in Swift 4.2, but will be supported in Swift 5.0. In addition, @J Doe posted below a way to accomplish this with an update to Xcode toolkit.
dynamic-stack-buffer-overflow
doesn't have anything to do with recursion. It means an alloca
buffer was overrun. Check the asan runtime source code.
Suppose the stack is laid out so that you have an alloca
buffer followed by an object pointer—maybe even one of the object pointers passed as an argument.
Suppose the alloca
buffer gets overrun. In an asan build, this can trigger a dynamic-stack-buffer-overflow
error. But in a non-asan build, it just writes over the bytes of that object pointer. Suppose it writes bytes that form an address that's not mapped in your process's page table.
If the program tries to read that object pointer and store it elsewhere (say, in an instance variable), it has to increment the reference count of the object. But that means dereferencing the pointer—and the pointer points to an unmapped address. Perhaps that's leading to a general protection fault, which Mach calls an EXC_I386_GPFLT
.
It would be helpful if you posted the stack trace of the asan dynamic-stack-buffer-overflow
error, and the disassembly of the code leading up to the error.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With