Contents

Zeal之深夜探索Bug

Contents

版本:0.3.1(当前官网最新 2017.8.2,貌似很久没更新过) zeal-0.3.1-windows-x86.msi(百度云有)

/posts/2017/zeal-bug-fix/res/1.png

Zeal每次下完文档程序就崩溃了,文档包也没生成。

/posts/2017/zeal-bug-fix/res/2.png

这个地方死循环了 我看这个函数像是CRT的函数 但是符号匹配不上,而且crt是动态链接的,所以这个函数肯定是它自己实现的 翻了crt的代码,有关errorno的,找到了_dosmaperror,那两张表刚好能对上 但是crt没有这样的代码逻辑,所以肯定是它自己实现了一份,看了这个函数的调用,在CreateFile失败之后,把GetLastError放进去,找映射的值,结果这二货不在表里,就一直越界了 哈哈,追了很长一段

/posts/2017/zeal-bug-fix/res/3.png

这就是那张表

/posts/2017/zeal-bug-fix/res/4.png

这是crt里面的实现,没问题。 你看它的代码,循环根本就没有边界。 然后我用Windbg把这个循环过掉,直接jmp,后面程序不崩溃了,打了个调试日志 Could not create D:/Zeal/*****

/posts/2017/zeal-bug-fix/res/5.jpg

原来是这里,如果Zeal文件夹不存在就挂了, CreateFile失败,GetLastError是120,这个错误没在那张表里面 突然在它的官网下面有个Github地址,原来是开源的。。。 我去,我就去翻了它的代码,看他为什么要这么写。 把代码Checkout下来,结果没搜到这部分的实现 开始我以为是Qt写的,查看这个函数的调用地方,有些字符串关键字,结果我就去Qt源码里搜,顿时SB了,Qt是动态链接的,当时没想起。

/posts/2017/zeal-bug-fix/res/6.png

洗完澡出来发现搜了10万多个文件,没收到,然后在github看到这个。

用到了libarchive,我把libarchive的代码拖了下来,搜索找到关键的字符串。

/posts/2017/zeal-bug-fix/res/7.png

libarchive在09年加入这部分代码,16年才修复这个bug。 这个代码是从PostgresSQL扣过来的,人家用LENGTHOF 我看他的提交记录说改成MinGW编译,就手贱改成了sizeof 刚刚那个Zeal就是用的这个老包。 但是我始终没明白为什么编译器会搞成 for(1),而不是sizeof数组的大小 我查看了Zeal的构建记录,它编译的lib是静态库,里面确实是for(1),但是代码肯定不可能编译成那个样子的啊 我试过了,VS、MinGW的Gcc都不会 奇葩啊,我准备抽空给它写个issue。喊他创建文件夹和更新一下官网的包 昨天晚上准备把go备份redmine的代码写完的,结果用这个去下go的文档,就挂了。试了好几次都这样,终于不能忍了。 结果后面追代码花了很长时间,代码也没写成。。。