MathType 因字体名称过长而崩溃的 Bug

MathType 版本:7.4.2.480 (从 6.9 到最新的 7.6 都有这个 bug )

问题:在安装“阿里巴巴普惠体”后, MathType 启动时崩溃退出,无错误信息显示。

附加调试器,错误为 STATUS_STACK_BUFFER_OVERRUN ,调用栈如下:

call stack

0050CE6D 是栈安全检查,出错位置在 00457D94 。根据调用分析可知函数是 EnumFontFamiliesExA 的回调函数。IDA 快速分析一下:

ida analyze

字符串复制时依赖了 ‘\0’ ,但根据微软文档,字符串如果长度超出最大长度,那么末尾就会被截断,所以可能不存在 ‘\0’ (这里微软文档写得不清楚):

LOGFONTA (wingdi.h)

lfFaceName[LF_FACESIZE]

A null-terminated string that specifies the typeface name of the font. The length of this string must not exceed 32 TCHAR values, including the terminating NULL. The EnumFontFamiliesEx function can be used to enumerate the typeface names of all currently available fonts. If lfFaceName is an empty string, GDI uses the first font that matches the other specified attributes.

阿里巴巴普惠体中最长的字体名是 阿里巴巴普惠体 2.0 95 ExtraBold ,利用 python 计算 len(s).encode('gbk') 为 31 ,加上 ‘\0’ 正好 32 ,和 LF_FACESIZE 一样大,为什么还会出现这样的问题?

在调试器中打条件断点:

字体本身是正常的:

dump 1

但是对于东亚字体,自动产生一个竖排字体,其名称前面多一个 ‘@’ ,所以刚好超出了字体的长度限制,导致发生崩溃。。

dump 2

修复:

找一块内存区域写代码,手动在变量最后填上 ‘\0’ ,这里选了上一个函数末尾由于对齐留下的空间:

code fix

最好的方法还是做一下 dll proxy ,否则会破坏数字签名。