此文章最初发布在以太坊博客.
Christoph Jentzsch 通过 以太坊基金会赏金计划 报告了 Solidity 优化器中的一个漏洞。此漏洞已于 2017-05-03 通过发布 Solidity 0.4.11 进行修复。
背景
该漏洞涉及优化器如何优化字节码中的常量。这里所说的“字节码常量”是指任何PUSH 到堆栈上的内容(不要与 Solidity 常量混淆)。例如,如果值 0xfffffffffffffffffffffffffffffffffffffffffffffffe 被 PUSH,则优化器可以选择执行 PUSH32 0xfffffffffffffffffffffffffffffffffffffffffffffffe,或者选择将其编码为 PUSH1 1; NOT;。
优化器中的错误导致在某些情况下字节码常量的优化失败,产生了无法正确重现原始常量的例程。
在报告的漏洞中描述的行为是在一个合约中发现的,其中一个方法在向合约中添加另一个完全无关的方法后停止工作。经过分析,确定触发此漏洞需要同时存在多个条件。任何触发此漏洞的条件组合都将始终包含以下两个条件
- 常量需要以 0xFF... 开头并以一系列零结尾(反之亦然)。
- 相同的常量需要在多个位置使用,以便优化器选择优化此特定常量。或者,它需要在构造函数中使用,构造函数会为了大小而非 Gas 进行优化。
除了上述两个条件外,还需要满足其他更复杂的条件。
分析
此漏洞存在于至少从 2015 年夏季到现在的所有已发布的 Solidity 版本中。尽管此漏洞自 2015 年以来就已存在,但似乎很难通过“随机”代码触发。
我们对区块链上部署的所有合约代码进行了静态分析,但未发现此类无效生成的例程。请注意,我们没有在所有合约代码中发现此漏洞并不保证此类情况不存在。
改进
为了提供更好的透明度和提高对 Solidity 中漏洞的认识,我们已开始以 JSON 文件的形式在 Solidity 代码库中导出有关 Solidity 相关漏洞的信息(1,2)。我们希望区块浏览器能够将此信息与其他合约相关信息一起集成。
Etherscan 已经实现了这一点,可以在 此处 和 此处 查看。
关于漏洞本身,我们在优化器中添加了一个迷你 EVM,它在编译时验证每个生成的例程的正确性。
此外,已经开始着手开发一个完全指定的、更高级别的中间语言。未来在此语言上的优化器例程将更容易理解和审计,并将取代当前的优化器。