为什么CLR的jmp指令无法验证?

naa*_*ing 14 c# clr cil

我已经了解了一段时间的jmp指令,但它从来没有让我觉得它甚至远程不安全.我最近有理由检查CIL规格,并且发现jmp被认为是无法验证的,我感到非常惊讶.

Dou*_*ean 4

因为,与 、 或 不同callcallvirt调用calli者的堆栈帧将保留在堆栈上,以便由被调用者触发(可能间接)的未来代码访问安全堆栈遍历看到,指令会在jmp转换到被调用者之前拆除调用者的堆栈帧因此对于被调用方可能触发的任何 CAS stackwalk 都是不可见的。

编辑:我认为纳斯金关于上述答案是错误的是正确的。我现在认为(可验证的)tail.call序列和(不可验证的)jmp序列之间的区别可能是尾调用需要将调用的参数推送到评估堆栈上,在那里它们可以以正常方式进行验证,而ajmp需要评估堆栈为空并导致jump-ee继承jump-er的参数。可能没有理由使验证器检查jmp指令变得复杂,但在类似于序列强加的条件下可能会这样做tail.call(其中之一是调用者和被调用者必须位于同一个程序集中,这排除了我的CAS 猜测如上,至少达到显式.Deny( )调用)。

如果是这样,这将是规范的相关部分:(第 III 部分,第 3.37 节)

当前参数将传输到目标方法。

执行该指令时,求值堆栈必须为空。目标地址处的调用约定、参数的数量和类型必须与当前方法的调用约定、数量和类型相匹配。