记重叠拷贝引发的“灵异事件”

项目组有一个工具用于生成配置文件。

我奉命为这个工具写配置模板,然后生成实际部署用的配置。现在这套工具部署在公司外其他提供商提供的机器上。

起初一切正常,在生成出配置后我拿部署在公司内的业务生成的配置进行对比。此时发现了一些很奇怪的现象。

生成出来的若干字符串中居然有的多了一个字符,有的有一个字符不一样。看上去就像人为拼错单词一样。

于是回去检查配置,但是一切正常。翻代码查看默认配置,依旧一切正常。

活了这么大第一次看见这种奇葩的问题,一般字符串出错有被截断的,有溢出Core掉的,就是没见过中间多一个字符少一个字符的。

二话不说开gdb调试,发现问题字符串从某函数中返回出来。翻源码检查,看上去没有什么不对的,于是将函数提出来,写了一个测试样例进行测试。

奇葩的现象又出现了,在公司的编译机上测试完全没问题。但是丢到外网的部署环境中,输出的字符串就莫名其妙多了一个字符。

“艹……这是踩到运行库的BUG了?”

这种感觉就跟中彩票一样,我的内心是震惊的。但是直觉告诉我一般是写代码的人踩到了运行库中UB的部分,于是回去review。

果然,在一个字符串剔除函数中看到了一段有问题的代码。

while (((*pb == ' ') || (*pb == '\t') || (*pb == '\n') || (*pb == '\r') || (*pb == '\'')) && (*pb != 0))
{
    pb ++;
}
pe = &strInput[iTempLength-1];
while ((pe >= pb) && ((*pe == ' ') || (*pe == '\t') || (*pe == '\n') || (*pe == '\r') || (*pe == '\'')))
{
    pe --;
}
*(pe+1) = '\0';
strcpy( strInput, pb );

写这段代码的人毫无疑问是想剔除首位不相干的字符,然后用strcpy将字符串移动到strInput的首部。然而操作全部在原始串上进行,造成了重叠拷贝的问题。

在公司环境中,C运行库兼容了这种做法,故而没有造成问题,而到了外网环境,由于运行库的差异致使暴露了这个问题。

由于这个工具不是非常重要,因此其他人没有当回事情,尤其发现在字符串末尾放置更多空格可以让这个问题消失掉,便没有进行深究了。

不过,至少说明养成良好的编程习惯还是很重要的:)