I've known about the jmp instruction for awhile, but it never struck me as being even remotely unsafe. I recently had cause to check the CIL specs and was very surprised to discover jmp is considered unverifiable.
Because, unlike a call
, callvirt
, or calli
, where the caller's stack frame would remain on the stack to be seen by future code access security stackwalks triggered (perhaps indirectly) by the callee, a jmp
instruction tears down the caller's stack frame prior to transitioning into the callee and is thus invisible to any CAS stackwalks that the callee may trigger.
Edit: I think naasking is right about the answer above being wrong. I now think the difference between (verifiable) tail.call sequences and (unverifiable) jmp sequences may be that a tail call requires pushing the arguments to the call onto the evaluation stack where they can be verified in the normal way, whereas a jmp
requires the evaluation stack to be empty and causes the jump-ee to inherit the arguments of the jump-er. There was probably no reason to complicate the verifier to check jmp
instructions, but it might be possible to do so under conditions similar to those imposed on tail.call
sequences (one of which is that the caller and callee must be in the same assembly, which rules out my CAS guess above, at least up to explicit .Deny( )
calls).
If so, this would be the relevant part of the spec: (Partition III, Section 3.37)
The current arguments are transferred to the destination method.
The evaluation stack must be empty when this instruction is executed. The calling convention, number and type of arguments at the destination address must match that of the current method.
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