[Issue 16106] New: Calling a fiber from itself causes hard-to-debug stack corruption
via Digitalmars-d-bugs
digitalmars-d-bugs at puremagic.com
Tue May 31 07:28:52 PDT 2016
https://issues.dlang.org/show_bug.cgi?id=16106
Issue ID: 16106
Summary: Calling a fiber from itself causes hard-to-debug stack
corruption
Product: D
Version: D2
Hardware: x86_64
OS: All
Status: NEW
Severity: enhancement
Priority: P1
Component: druntime
Assignee: nobody at puremagic.com
Reporter: clugdbug at yahoo.com.au
If you are in fiber `f`, and you call `f.call()`, then you are switching the
context to yourself.
There is an `in` contract in Fiber.call() which is meant to prevent this:
assert( m_state == State.HOLD );
That assert will fail, because the fiber is running. But if contracts are
disabled, then execution will continue anyway.
Conceptually, switching context to yourself is a no-op. The function could
simply return. I'm not sure that would be a good idea, but it's certainly
possible. And it *almost* behaves that way. The function fiber_switchContext()
pushes the registers onto the existing stack, then pops them from the new
stack.
In this case, the old stack and new stack are the same. Except that the new
stack pointer is the top of the new stack *before the pushes were made*.
So, it loads the registers from the completely wrong place. If you're lucky,
you get a segfault. If you don't, you'll end up in a completely unrelated
place. Either way it is quite difficult to diagnose why it has happened.
Admittedly, this only happens after an 'in' contract violation. But I think we
should do something a bit more robust.
The check for ``m_state == State.HOLD`` is not expensive (one CMP and a
predictable branch). It should be moved out of the contract into the function
body. The consequences of a totally corrupt stack are _extremely_ severe. It's
worth sacrificing a single clock cycle to prevent this debugging nightmare.
--
More information about the Digitalmars-d-bugs
mailing list