使用以前版本的编译器是否可以防止代码注入?

v.o*_*dou 29 c c++ compiler-construction compilation

我想知道今天的现代编译器,如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的缺陷?

因此,如果他们是自己建造的,他们如何保护自己?

Eri*_*ert 25

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

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

如果构建链中某处某些变态扭曲是由于纯错误引入的,那么今天的编译器生成错误的代码,即使编译器的源代码看起来还行

这是一个严重的问题.

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

减轻这种风险的方式当然与减轻与坏工具相关的任何风险的方式相同:您将各种版本的编译器工具检入存储库,以便您可以回滚到先前已知良好版本的编译器你需要吗?你大量测试编译器.

  • @ v.oddou:仔细阅读我的场景.编译器Alpha和Beta不需要具有相同的输出; 这是两个不同的编译器,具有不同的源代码和不同的行为.但肯定编译器Beta和Gamma应该具有相同的行为,因为它们是从相同的源代码编译的.如果使用Alpha编译的Beta源和使用Beta编译的Beta源为编译器提供不同的行为,则Beta可能存在问题. (3认同)

use*_*421 5

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

当然,某些语言不能用于编译器编写.

编辑应该明确的是,当实质性问题是"编译器是否使用以前版本的编译器构建?"时,会发布此答案.它后来被改变了.

  • "当然有些语言不能用于编译器编写." 除非我们包含真正特定于域的语言,否则此声明是不真实的.任何具有I/O的图灵完备语言都可用于为任何其他语言实现编译器. (3认同)
  • @nibot在实践中并非如此.例如,在COBOL中编写COBOL编译器在经济上是不可行的,并且只有疯子会尝试它.我没有.缺少太多东西:递归,一开始. (3认同)
  • @nibot:我挑战你写一个自托管PL/SQL编译器,或ABAP ... ;-)我们只是说,有些语言不能*合理地*用于编译器编写.(虽然我听说过BF编写的BF编译器,但BF是一种在没有引号的同一句话中不能用"合理"提及的语言.;-)) (2认同)