zlib解压失败

10

我正在编写一个应用程序,需要解压另一个应用程序(我无法控制 - 无法更改其源代码)压缩的数据。生产者应用程序使用zlib来使用z_stream机制压缩数据。它经常使用Z_FULL_FLUSH(在我看来可能过于频繁,但这是另一个问题)。这个第三方应用程序也能够解压自己的数据,所以我相信数据本身是正确的。

在我的测试中,我使用这个第三方应用程序来压缩以下简单文本文件(十六进制):

48 65 6c 6c 6f 20 57 6f 72 6c 64 21 0d 0a

我从应用程序接收到的压缩字节如下(同样以十六进制表示):

78 9c f2 48 cd c9 c9 57 08 cf 2f ca 49 51 e4 e5 02 00 00 00 ff ff

如果我尝试压缩相同的数据,我会得到非常相似的结果:

78 9c f3 48 cd c9 c9 57 08 cf 2f ca 49 51 e4 e5 02 00 24 e9 04 55

我可以看到有两个区别:

首先,第四个字节是F2,而不是F3,因此deflate的“最终块”位没有设置。我认为这是因为流接口永远不知道传入数据的结尾将是什么,所以从未设置该位?

最后,外部数据中的最后四个字节是00 00 FF FF,而在我的测试数据中是24 E9 04 55。搜索一下,我在这个页面上找到了答案:

http://www.bolet.org/~pornin/deflate-flush.html

...表明这是同步或完整刷新的标志。

当我尝试使用decompress()函数解压自己的数据时,一切都能正常工作。然而,当我尝试解压外部数据时,decompress()函数调用失败并返回错误码Z_DATA_ERROR,表示数据已损坏。

我有几个问题:

  1. 我能否使用zlib的“uncompress”函数来解压使用z_stream方法压缩的数据?

  2. 在上面的示例中,最后四个字节的意义是什么?考虑到外部压缩数据流和我的测试数据流长度相同,我的最后四个字节代表什么?

谢谢


我对此一无所知,但你在问题中忘记添加的一个可能相关的信息是:zlib 解压是如何失败的。 - Vinko Vrsalovic
2个回答

9
感谢zlib的作者,我已经找到了答案。第三方应用程序生成的zlib流没有正确地结束:
78 9c f2 48 cd c9 c9 57 08 cf 2f ca 49 51 e4 e5 02 00 00 00 ff ff
这是一个部分的zlib流, 由zlib头和部分deflate流组成。 有两个块,都不是最后一个块。 第二个块是一个空的存储块,在刷新时用作标记。 zlib解码器会正确解码其中的内容, 然后继续寻找这些字节之后的数据。
78 9c f3 48 cd c9 c9 57 08 cf 2f ca 49 51 e4 e5 02 00 24 e9 04 55
这是一个完整的zlib流, 由zlib头、一个标记为最后一个块的单个块和一个zlib尾部组成。 尾部是未压缩数据的Adler-32校验和。
所以我的解压失败了 - 可能是因为缺少CRC, 或者解压缩代码一直在寻找不存在的更多数据。

你的回答没有解决我的问题,但是它确实导致了一个解决方案。原来我试图在流的中间解压缩部分zlib流。你应该从流的开头开始解压缩,然后随着数据块的到来逐步添加。(例如使用Python的zlib.decompressobj().decompress(part),如此处所示:https://dev59.com/y3rZa4cB1Zd3GeqP1FIX) - serg06

3

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接