Hos*_*ork 6 c compression gzip zlib
我正在将项目的代码从1998版的zlib更新为2013版的zlib.似乎改变的一件事是,uncompress函数曾经有一个"use_crc"标志,似乎已经丢失了:
int ZEXPORT uncompress (dest, destLen, source, sourceLen, use_crc)
Bytef *dest;
uLongf *destLen;
const Bytef *source;
uLong sourceLen;
int use_crc; // <-- vanished (?)
Run Code Online (Sandbox Code Playgroud)
(更新:正如@Joe所指出的,这很可能是第三方修改.标题也相应更新.问题的其余部分仍然适用,例如,"我应该如何利用今天的股票zlib做到最好".)
在我正在研究的代码中,uncompress()被解析为.zip的二进制格式并传入数据的"有效负载".代码已经将crc标志传递为1.如果未使用该标志,则会获得Z_DATA_ERROR(-3).(没有use_crc标志的zlib获得Z_DATA_ERROR,就像标志为false一样.)
在实验中,我发现非常小的文件没有use_crc.然后小的计数文件交叉到"12345678901234"和之间不工作"123456789012345".原因是:这是第一个被放气而不是存储未压缩的文件(在什么拉链称为"6%"的节省)
在挣扎着让zlib接受它的选项时,我尝试了很多东西.这包括尝试16 + MAX_WBITS.似乎没有任何东西像zip test.zip test.txt那样处理旧有代码的方式.
如果我愿意从我的目的地大小中减去一个,我似乎能够抑制错误检查......丢失一个字节.这是简单的测试程序,最小拉链有效负载硬编码:
#include <stdio.h>
#include "zlib.h"
int main(int argc, char *argv[]) {
char compressed[] = { 0x78, 0x9C, 0x33, 0x34, 0x32, 0x36, 0x31, 0x35, 0x33,
0xB7, 0xB0, 0x34, 0x30, 0x04, 0xB1, 0xB8, 0x00, 0x31, 0x30, 0xB1, 0x30,
0x10, 0x00, 0x00, 0x00 }; // last 4 bytes are size (16)
char uncompressed[16 + 1]; // account for null terminator
int ret; z_stream strm;
memset(uncompressed, 'X', 16);
uncompressed[16] = '\0';
strm.zalloc = strm.zfree = strm.opaque = Z_NULL;
strm.total_out = 0;
strm.avail_in = 25;
strm.next_in = compressed;
ret = inflateInit2(&strm, MAX_WBITS /* + 16 */); // it is Z_OK
strm.avail_out = 15; // 16 gives error -3: "incorrect header check"
strm.next_out = uncompressed;
ret = inflate(&strm, Z_NO_FLUSH);
if (ret != /* Z_STREAM_END */ Z_OK) { // doesn't finish...
printf("inflate() error %d: %s\n", ret, strm.msg);
return 2;
}
inflateEnd(&strm);
printf("successful inflation: %s\n", uncompressed);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
输出是:
成功通胀:123456789012345X
显示数据正在解压缩,但我们需要所有16个字节. (应该接收的文件中有一个换行符.) 16 + MAX_WBITS甚至无法获得.
有什么想法会出错吗?没有设置的排列似乎没有错误.
不,自 20 多年前推出以来,zlib 接口没有发生不兼容的更改。从来没有use_crc争论过uncompress()。
你给的例子是一个两字节的zlib头,DEFLATE压缩数据,该CRC-32在放气数据的大-endian顺序,随后在一个四字节的长度小-endian顺序。这是 zlib 和 gzip 包装器的真正奇怪的混搭,与您一直提到的 zip 格式没有任何关系。(您的意思是“zip 文件中的有效负载”是什么意思?)zlib 在大端顺序的末尾有一个 Adler-32,而 gzip 有一个小端顺序的 CRC-32,后跟一个四字节长度的小端-端序。这个混淆了这些,包括字节顺序,然后故意误导性地将一个有效的 zlib 标头放在这个东西上,这是对这个世界上所有美好和体面的侮辱。
我很确定当时提出这种格式的人喝醉了。
为了解码这个,你需要:
丢弃流的前两个字节。(您可以检查它是否是有效的 zlib 标头,但结果证明在解释流的其余部分时毫无意义。)
使用原始 deflate,用 , 初始化inflateInit2(&strm, -15)来解压数据。解压缩时,请跟踪总长度并使用 计算 CRC-32 crc32()。
deflate 数据完成后,读取接下来的四个字节,按大端顺序将它们组合成 32 位值,并将其与您计算的 CRC-32 进行比较。如果不匹配,则该流已损坏,或者它不是这些格式奇怪的流之一。(也许再试一次,将其解码为普通的 zlib 流。如果它有一个好的 zlib 标头,那么也许这就是它的实际情况,而不是这些 Frankenstein 流之一。)
读取接下来的四个字节并按小端顺序组装它们,并将其与未压缩数据的长度进行比较。如果不匹配,则流已损坏,或者不是您所想的。
如果数据没有在这里结束,那么其他奇怪的事情正在发生。咨询醉酒的人。
| 归档时间: |
|
| 查看次数: |
143 次 |
| 最近记录: |