Я знаю об инструкции jmp некоторое время, но это никогда не поразило меня как даже отдаленно небезопасное. Недавно мне пришлось проверять спецификации CIL и был очень удивлен, обнаружив, что jmp считается непроверенным.
Почему команда CLR jmp не поддается проверке?
Ответ 1
Потому что, в отличие от call
, callvirt
или calli
, где фрейм стека вызывающего абонента останется в стеке, который будет рассматриваться будущими защитными стеками безопасности доступа к коду, вызванным (возможно, косвенно) вызываемым, a jmp
срывает кадр стека вызывающего абонента перед тем, как перейти к вызываемому абоненту и, таким образом, невидимо для любых стеков стека CAS, которые вызывающий может вызвать.
Редактирование: я считаю, что naasking прав насчет неправильного ответа. Теперь я думаю, что разница между (проверяемыми) tail.call последовательностями и (непроверяемыми) jmp-последовательностями может заключаться в том, что хвостовой вызов требует нажатие аргументов на вызов в стек оценки, где они могут быть проверены обычным способом, тогда как a jmp
требует, чтобы стек оценки был пустым и заставлял jump-ee наследовать аргументы jump-er. Вероятно, не было причины усложнять верификатор для проверки инструкций jmp
, но это может быть возможно в условиях, аналогичных тем, которые накладываются на последовательности tail.call
(один из которых заключается в том, что вызывающий и вызываемый должны быть в одном и том же сборка, которая исключает мое предположение CAS выше, по крайней мере, до явных вызовов .Deny( )
).
Если это так, это будет соответствующей частью спецификации: (раздел III, раздел 3.37)
Текущие аргументы передаются к методу назначения.
Стол оценки должен быть пустым когда эта инструкция выполнена. вызов, количество и тип аргументы по адресу назначения должен соответствовать текущему методу.