扫一扫
分享文章到微信
扫一扫
关注官方公众号
至顶头条
作者:Demien Watkins 2007年10月26日
关键字: net
在运行库会进行两种形式的验证:MSIL 验证和程序集元数据验证。运行库中的所有类型都指定了它们将要实现的协定,这些信息将作为元数据与 MSIL 一起保留在托管 PE/COEFF 文件中。例如,如果一个类型指定它从另一个类或接口进行继承,这就表明它将要实现一些方法,这就是一个协定。协定也可以与可见性联系起来。例如,可以将类型声明为从它们的程序集公开(导出)或其他的内容。因为类型安全只能根据它们的协定访问类型,所以就此而言,它是代码的一个属性。可以验证 MSIL 以证明它是类型安全的。验证是 .NET 框架安全系统中的一个基本构造块,目前只在托管代码上执行验证。因为非托管代码不可由运行库进行验证,所以由运行库执行的非托管代码必须是完全受信任的。
要理解 MSIL 验证,关键在于理解如何对 MSIL 进行分类。MSIL 分为下列类型:无效的 MSIL、有效的 MSIL、类型安全的 MSIL 以及可验证的 MSIL。
注 应该指出的是,下面的定义比标准定义提供了更多信息。有关更加准确的定义版本,请参阅其他文档,如 ECMA standard:
无效 MSIL 是 JIT 编译器无法为它生成本机表示的 MSIL。例如,不能将包含无效操作码的 MSIL 翻译成本机代码。另一个示例是跳转指令,该指令的目标是操作数的地址,而不是操作码。
有效 MSIL 可以被认为是满足 MSIL 语法的所有 MSIL,因此它可以用本机代码表示。这种分类包括的 MSIL 可以使用非类型安全形式的指针算法获取对类型成员的访问。
类型安全的 MSIL 只通过它们向公众公开的协定与类型进行交互。试图从一个类型访问另一个类型的私有成员的 MSIL 就不是类型安全的。
可验证的 MSIL 是可以通过一个验证算法来证明是类型安全的 MSIL。验证算法比较保守,因此某些类型安全的 MSIL 可能不会通过验证。当然,可验证的 MSIL 既是类型安全的又是有效的,当然不是无效的。
除了类型安全检查之外,运行库中的 MSIL 验证算法还会检查堆栈上溢/下溢的发生、异常处理工具的正确使用以及对象初始化。
对于从磁盘加载的代码,验证过程是 JIT 编译器的一部分,它会在 JIT 编译器中间歇性地进行。验证和 JIT 编译不是作为两个独立的进程来执行的。如果验证期间在程序集中找到了一连串不可验证的 MSIL,那么安全系统就会检查该程序是否足够受信任,可以跳过验证。例如,如果一个程序集是在安全模型的默认设置下从本地硬盘上加载的,那可能就是这样的情况。如果程序集受信任,可以跳过验证,则会将 MSIL 翻译成本机代码。如果程序集的受信任程度不够,不能跳过验证,则会用一个存根来代替有问题的 MSIL,如果使用了该执行路径,该存根就会引发一个异常。一个常见的问题是:“为什么不在验证程序集之前检查它是否需要验证呢?”因为验证通常是作为 JIT 编译的一部分执行的,所以它通常比检查是否允许程序集跳过验证更快。(决定跳过验证比这里描述的过程更加智能。例如,可以缓存前面一些验证尝试的结果,以提供快速的查找方案。)
除了 MSIL 验证之外,还要验证程序集元数据。事实上,类型安全依赖于这些元数据检查,因为它假定 MSIL 验证期间使用的元数据标记是正确的。在全局程序集缓存 (GAC) 或下载缓存中加载程序集时,会验证程序集元数据;如果没有将它插入到 GAC 中,则从磁盘中读取它时也会验证程序集元数据。(GAC 是一些程序使用的程序集的中央存储。下载缓存保存了从其他位置(如 Internet)下载的程序集。)元数据验证包括检查元数据标记和消除缓冲区溢出,前者用于检查它们是否会正确索引到它们访问的表中,以及到字符串表的索引是否并不指向长度大于应该保存它们的缓冲区大小的字符串。通过 MSIL 验证和元数据验证来消除非类型安全的类型安全代码是运行库安全性的第一部分。
查看本文来源如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。
现场直击|2021世界人工智能大会
直击5G创新地带,就在2021MWC上海
5G已至 转型当时——服务提供商如何把握转型的绝佳时机
寻找自己的Flag
华为开发者大会2020(Cloud)- 科技行者