Windows 上的 ZLIB:gzopen/gzwrite/gzclose 会产生阉割输出文件/防病毒错误?
几天来我一直在追寻一个非常神秘的错误,它似乎围绕 (ZLIB 库); 它大约每月发生一次,并且仅在某些特定的生产环境中发生。 该代码的作用如下:
- 程序调用
gzopen
写入文件X
。 - 程序将数据写入文件,执行多次
gzwrite
。 - 程序最终调用
gzclose
来刷新文件。
通常,一切正常并且文件 X
有效; 它通过 CRC 和源流的长度正确终止。
然而,在其中一次失败中,我观察到 X
已损坏:数据的开头是正确的,但从偏移量 0x00302000
开始,每个字节都是空的。 甚至最后八个字节(编码 CRC 和长度)也为零。 但是,该文件的大小正确! 更糟糕的是:同一系统在几分钟前成功压缩了一个非常相似的文件。
注意:我们使用的ZLIB.DLL版本为1.1.3; 是的,我知道,它包含一些安全漏洞,我们应该升级到最新的 ZLIB 1.2.3,但在找到归零的原因之前,我不想更改我的设置中的任何内容。
我认为我已经排除了内存损坏的可能性(顺便说一句,损坏的内存堆如何充分干扰 fwrite
以至于它只向输出流写入零?这可能吗?),循环打开/写入/关闭流很简单,并且没有揭示我可以发现的任何缺陷,代码不会分配/释放/混乱 ZLIB 中的结构(这可能是一个问题,因为 ZLIB 链接到另一个 C 库,而不是我的)应用程序 DLL),所以我只能怀疑系统中的其他元素。
不知何故,我倾向于对C库(CRTDLL.DLL)、Win32 API、NTFS堆栈、I/O堆栈、低级设备驱动程序、硬盘固件和硬盘本身有信心......是的,我也倾向于相信 Visual C++ 2008 会生成正确的二进制文件,至少在这种情况下是这样;-)
那么,我怀疑防病毒软件可能是罪魁祸首是否正确? 应谨慎对待 ZLIB,因为至少卡巴斯基将 DLL 视为可能的威胁。 但是,如果(错误地)发现感染,防病毒软件简单地写入零而不是数据在政治上是否正确? 或者这可能是防病毒软件中的一个错误?
或者我完全没有抓住重点?
I've been chasing a very mysterious bug for days now, which seems to revolve around the (ZLIB library); it occurs once every month or so, and only on some specific production environments. Here is what the code does:
- The program calls
gzopen
to write to a fileX
. - The program writes data to the file, doing several
gzwrite
. - The program finally calls
gzclose
which flushes the file.
Usually, everything works fine and the file X
is valid; it is properly terminated with the CRC and the length of the source stream.
However, in one of the failures, I observe that X
is corrupt: the beginning of the data is correct, but starting at offset 0x00302000
, every byte is null. Even the eight last bytes, which encode the CRC and the length, are zero. However, the file has the right size! And what's worse: the same system successfully compressed a very similar file a few minutes earlier.
Note: The ZLIB.DLL we are using has the version 1.1.3; yes, I know, it contains some security holes and we should upgrade to the latest ZLIB 1.2.3, but I don't want to change anything in my setup until I've found the cause of the zeroing.
I think that I've ruled out memory corruption (by the way, how could a corrupt memory heap disturb fwrite
sufficiently that it only writes zeroes to the output stream? would that be plausible?), the loop which opens/writes/closes the stream is simple and does not reveal any defects I can spot, the code does not allocate/free/mess with structures in ZLIB (which could be a problem, since ZLIB is linked against another C library than my application DLLs), so I can only suspect other elements in the system.
Somehow, I tend to have confidence in the C library (CRTDLL.DLL), the Win32 API, the NTFS stack, the I/O stack, the low-level device drivers, the firmware of the harddisks and the harddisk themselves... And yes, I also tend to believe that Visual C++ 2008 produces correct binaries, at least in this case ;-)
So, am I right to suspect that the antivirus software could be the culprit? It should be cautious with ZLIB, since at least Kaspersky recognizes the DLL as a possible threat. But would it be politically correct for an antivirus to simply write zeroes instead of the data if an infection is (incorrectly) spotted? Or might this be a bug in the antivirus?
Or do I totally miss the point?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
在不知道其他任何事情的情况下,我会怀疑你的代码,而不是防病毒代码。
将正确长度的数据写入文件需要一个简单的错误,但传入不正确的缓冲区,导致文件中的数据为“全零”。
难以发现的简单错误有时会导致非常大的混乱,就像您所遇到的那样。
如果我要解决这个问题,我会:
在正常情况下,GZIP 数据永远不会有一长串的零。 这些将被折叠成字典和长度代码。
Without knowing anything else, I would suspect your code, rather than the anti-virus code.
It would require a simple error to write the correct length of data to the file, but passing in an incorrect buffer, resulting in "all zeroes" as data in the file.
Simple errors that are hard to spot sometimes lead to very big confusion, like you are having.
If I were troubleshooting this I would:
In normal circumstances, GZIP'd data will never have a looong succession of zeros. These will be collapsed into a dictionary and length code.