这是一个隐藏很深的bug因电脑升级而暴露出来的例子。
Protel99se是2000年前后推出的电子设计软件,包含画原理图、画PCB、CAM、电路仿真等功能。它用法简明,能满足大多数情况下PCB设计的需求,而且在低性能电脑上也能流畅运行。至今仍有大量老一辈工程师在使用,因此PCB工厂也必须兼容这种陈旧的文件格式。
2008年左右大家渐渐开始发现,在保存工程时,有时会弹出这样的错误框
熟悉C语言的你肯定知道,这是printf这类函数的格式化字符串参数写错了。但搞电子设计的前辈工程师们并不懂得这么深入。
终于有一天,一位EE与IT双修的年轻大佬用OllyDbg探查,揭开了谜底。
原来,软件中有这样一个函数,每次调用生成一个随机文件名,用于临时文件。核心逻辑写成伪代码是这样的
def
get_random_file_name
():
随机数
=
GetTickCount
()
#1
文件名
=
'
%s
\
%s%x
.tmp'
%
(
**
,
**
,
随机数
)
while
True
:
if
文件名不存在
:
break
随机数
=
GetTickCount
()
文件名
=
'
%s
\s
%x
%.tmp'
%
(
**
,
**
,
随机数
)
#2
return
文件名
如果硬盘很快,迅速保存好了前一个文件,就会导致下次调用的间隔太短,1处会返回同一个值,于是执行到2处。而2处的格式字符串写错了。所以,高性能电脑就会触发这个bug。
字符串位于文字池里,是明文存储的,所以只要搜索这串文字并改正就好了,可以直接给exe文件打补丁。这位大佬同时发布了这个二进制补丁。
参考资料
[原创]关于出现 Protel 99 SE 'Format '%x' invalid or incompatible with argument' 的分析
针对评论区补充一下。
伪代码只是展示程序逻辑,我用python当皮套只因它精练。
据大佬分析,源程序是delphi写的,并不是C艹。上述伪代码展现的业务逻辑是先用ida插件从汇编反推C再简化而来的,万恶之源的delphi源码是怎么写的已经不得而知了。