上周,我试图向libsecp256k1添加一些测试代码,我拔掉头发试图让它正常工作。没有多少printf工作来说明我做错了什么。最后,出于无奈,我想我应该快速检查一下是否有与memcmp相关的编译器错误,结果,我发现了GCC错误#95189:memcmp像strcmp一样被错误地剥离。
老实说,读起来这是一个相当可怕的错误。在某些情况下,当其中一个输入是静态已知的包含空字节的数组时,GCC 9和10会导致memcmp返回不正确的值。当我急忙用GCC 8重新编译我的计算机系统时,我考虑了这样一个错误可能带来的巨大后果,并思考计算机怎么可能工作。
然而,在一周的时间里,在同事的帮助下,我们设法更好地了解了错误的范围。错误只能将非零值转换为零值。静态数组的前4个字节中需要有一个空字节。最重要的是,memcmp的结果不能立即与0进行相等或不相等的比较,或者任何等价的测试。在这种情况下,编译器中采用了不同的代码路径。这就解释了为什么计算机仍然可以正常工作。我希望绝大多数memcmp的使用都会立即与0进行相等测试。
不过,我仍然想知道,有多少代码受到了影响。我的同事蒂姆建议,可以在GCC将要错误编译程序的时候插入工具发出一条消息。我们给GCC 9和10打了一个补丁,可以打印一条调试消息。我再次重新编译了我的整个系统,看看GCC在错误编译什么。我发现的情况是这样的:
在我的整个系统上,我只发现了10行错误编译的代码。有3行是测试的。所有行都可以重写,作为与0的对比。没有一行看起来那么严重。我不确定哪一行更糟糕:减少的消息完整性代码(?)。来自某个ARCFOUR实现,还是来自自动取款机驱动程序的某些东西?
Mplayer错误编译是最神秘的。围绕该函数的所有代码似乎都会立即将memcmp与0进行比较。考虑到我的调试消息拒绝确切指出该函数中的哪一行被错误编译,我担心某些优化恰好允许以某种方式错误编译此代码。
有了更多的硬件,我可以更彻底地调查这个GCC漏洞的后果,在此之前,我将坚持使用GCC 8,直到GCC 9和10有新的点发布。