【问题标题】:Are compilers built with previous version of themselves protected from code injection?使用以前版本的编译器构建的编译器是否可以防止代码注入?
【发布时间】:2014-05-06 01:21:12
【问题描述】:

我想知道今天的现代编译器,如 MS cc、gcc、clang、icc,是否使用相同编译器的当前版本构建了新版本?

因为当然有这个风险:
http://scienceblogs.com/goodmath/2007/04/15/strange-loops-dennis-ritchie-a/
http://c2.com/cgi/wiki?TheKenThompsonHack

相信参与上述编译器开发的每个人都知道这个问题,即代码由自身的早期版本注入编译器并无形传播。

现在真正的问题不是后门,而是更多关于代码生成正确性的问题,不是吗?如果在构建链中的某个地方由于纯错误而引入了一些变态扭曲,并且由于 Ken Thompson 的缺陷,即使编译器的源代码看起来不错,今天的编译器也会生成不正确的代码,该怎么办?

那么如果它们是自己建造的,它们如何保护自己呢?

【问题讨论】:

  • @DevSolar: opinion based? 认真的吗?你对完全可验证的 EJP 的评论有什么看法?你为什么不给回答的实施者一个机会呢?这个社区里有微软的人。我敢肯定也有 GCC 贡献者。
  • 可能。怎么样:传送带系统是在工厂中使用传送带建造的吗?机器人是用机器人制造的(还是手工制造的)?计算机是用计算机设计的(还是在纸上绘制的)?
  • 为了获得对编译器的信心,您将 (a) 使用来自不同制造商的多个编译器对其进行编译;这显然会产生不同的二进制文件,然后(b)用这些不同的二进制文件编译它,然后应该给出相同的二进制文件。那是一个可以编译它所用语言的编译器; COBOL 编译器可能不是用 COBOL 编写的。

标签: c++ c compiler-construction compilation


【解决方案1】:

我想知道今天的现代编译器,如 MS cc、gcc、clang、icc,是否使用相同编译器的当前版本构建了新版本?

Roslyn C# 编译器可以自行构建;事实上,它是它自己最好的测试用例之一。当然,它不能在第一天甚至第 100 天这样做;它是使用以前版本的 C# 编译器构建的,它是用 C++ 编写的。

如果在构建链中的某个地方由于纯粹的错误引入了一些变态扭曲,而今天的编译器生成不正确的代码,即使编译器的源代码看起来不错

这是一个严重的问题。

在自构建编译器中查找错误的一种有趣方法如下:调用原始的非自构建编译器 Alpha。使用 Alpha 构建新的源代码以生成 Beta。然后让 Beta 构建源代码以生成 Gamma。然后让 Gamma 构建源代码以生成 Delta。如果为 Gamma 和 Delta 生成的二进制文件存在显着差异,则您可能会遇到问题。给定相同的输入,Beta 和 Gamma 应该具有相同的输出。 (特别是 C# 不保证两次编译相同的代码会产生完全相同的二进制文件,因此您必须小心确保您的测试足够复杂以考虑到这一点。)

您减轻这种风险的方式当然与减轻与不良工具相关的任何风险的方式相同:您将各种版本的编译器工具签入到存储库中,以便您可以回滚到以前的已知良好版本如果你需要编译器。而且你对编译器进行了大量测试。

【讨论】:

  • 在引导程序和多样化双重编译中让我感到困惑的是,我无法理解我们应该通过什么奇迹获得“相同的输出”?因为存在新版本的编译器是因为它生成了更好的汇编(更优化),因此使用不同版本或供应商编译编译器总是会导致不同的输出,因为代码生成中的实现选择不同。证明:yosoygames.com.ar/wp/2013/12/…
  • @v.oddou:再次仔细阅读我的场景。编译器 Alpha 和 Beta 不需要有相同的输出;这是两个不同的编译器,具有不同的源代码和不同的行为。但毫无疑问,编译器 Beta 和 Gamma 应该具有相同的行为,因为它们是从相同的源代码编译的。如果用 Alpha 编译的 Beta 源代码和用 Beta 编译的 Beta 源代码给编译器的行为不同,那么 Beta 可能有问题。
  • 感谢您的帮助 :) 好的,我已经制作了这个图表:postimg.org/image/p4lqovfwn 现在我承认测试的二进制 1 和 2 应该是等价的(模 __TIME__ 宏的东西)但是 @987654324 @ 和 Blue Beta 将是不同的二进制文件,尽管应该尊重输入/输出对称性,但由于 AlphaBeta。所以这两个二进制文件实际上是非常不同的。我仍然想念一些东西
  • 我想我正在理解的路上(这就是我这次接受你的答案的原因),Gamma 是“第二链构建”,因此它应该等同于Beta,因为它只是重建?这可以证明吗?
【解决方案2】:

一般来说,对于以自己的语言实现的编译器来说,答案是“是”。自行构建编译器是正确性的最佳测试之一。连续运行应继续生成相同的二进制文件。例如,“GC”是使用四阶段引导过程构建的。

当然有些语言不能用于编译器编写。

编辑 应该明确的是,这个答案是在实质性问题是“编译器是用自己的先前版本构建的吗?”时发布的。后来又改了。

【讨论】:

  • "当然有些语言不能用于编译器编写。"除非我们包含真正特定领域的语言,否则这种说法是不正确的。任何具有 I/O 的图灵完备语言都可用于为任何其他语言实现编译器。
  • @nibot 实际上并非如此。例如,用 COBOL 编写 COBOL 编译器在经济上是不可行的,只有疯子才会尝试。我没有。缺少太多东西:首先是递归。
  • @nibot:我挑战你编写一个自托管的 PL/SQL 编译器,或 ABAP... ;-) 我们只是说,有些语言不能合理地使用用于编译器编写。 (虽然听说过 BF 写的 BF 编译器,而且 BF 是同句中不带引号不能用“合理”提及的语言。;-))
  • @nibot 您还忽略了运行时库的问题。你不能在 Cobol 中为 Cobol 编写运行时库。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-01-16
  • 2018-02-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-04-28
相关资源
最近更新 更多