我知道 jmp 指令有一段时间了,但我从来没有觉得它有一点不安全。我最近有理由检查 CIL 规范和 was very surprised to discover jmp is considered unverifiable .
最佳答案
因为,与 call
、callvirt
或 calli
不同,调用者的堆栈帧将保留在堆栈中以供将来查看由被调用者触发(可能间接)的代码访问安全堆栈遍历,jmp
指令在转换到被调用者之前拆除调用者的堆栈帧,因此对于被调用者可能触发的任何 CAS 堆栈遍历都是不可见的。
编辑:我认为 naasking 是正确的关于上面的答案是错误的。我现在认为(可验证的)tail.call 序列和(不可验证的)jmp 序列之间的区别可能是尾调用需要将调用的参数插入评估堆栈,在那里它们可以以正常方式验证,而 jmp
要求评估堆栈为空并导致 jump-ee 继承跳转的参数-呃。可能没有理由让验证器复杂化以检查 jmp
指令,但在类似于 tail.call
序列(其中之一也就是说,调用者和被调用者必须在同一个程序集中,这排除了我上面的 CAS 猜测,至少在显式 .Deny( )
调用之前是这样。
如果是这样,这将是规范的相关部分:(第 III 部分,第 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.
关于c# - 为什么 CLR 的 jmp 指令无法验证?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2853794/