[英]What guarantees does zlib's inflate/deflate make about avail_in and avail_out?
没有什么保障zlib
给出的状态avail_in
的avail_out
后调用inflate
? 我正在查看miniz
特殊行为,我想确保这不是对zlib
API的误解。 实际上,打完电话后inflate
,我已经avail_in
非零和avail_out
也非零,所以一些输入看起来是没有得到处理。 下面有更多详细信息。
我一直在使用miniz对从磁盘流到/从磁盘流过的文件进行膨胀/ 收缩 。 我的inflate / deflate循环与zpipe.c中的zlib示例相同,包括使用MZ_NO_FLUSH
。
这个循环几乎一直都起作用,但是今天我膨胀了一个早先放气的流,并始终得到MZ_DATA_ERROR
。 不过,在添加了适当的标头之后, gzip
便可以对其进行良好的充气,并且我的数据是完整的。
我问题的根源在于对mz_inflate
的最后一次调用。 我在这里包括典型的膨胀循环:
/* decompress until deflate stream ends or end of file */
do {
strm.avail_in = fread(in, 1, CHUNK, source);
if (ferror(source)) {
(void)inflateEnd(&strm);
return Z_ERRNO;
}
if (strm.avail_in == 0)
break;
strm.next_in = in;
/* run inflate() on input until output buffer not full */
do {
strm.avail_out = CHUNK;
strm.next_out = out;
ret = inflate(&strm, Z_NO_FLUSH);
assert(ret != Z_STREAM_ERROR); /* state not clobbered */
switch (ret) {
case Z_NEED_DICT:
ret = Z_DATA_ERROR; /* and fall through */
case Z_DATA_ERROR:
case Z_MEM_ERROR:
(void)inflateEnd(&strm);
return ret;
}
have = CHUNK - strm.avail_out;
if (fwrite(out, 1, have, dest) != have || ferror(dest)) {
(void)inflateEnd(&strm);
return Z_ERRNO;
}
} while (strm.avail_out == 0);
/* done when inflate() says it's done */
} while (ret != Z_STREAM_END);
重复do
内部do
循环,直到处理avail_out
所有当前块,并且avail_out
具有额外空间avail_out
。 然而,在这个特别的流的最后一块, inflate
并没有返回错误,而是会降低avail_in
一些非零数字,并会减少avail_out
也给一些(其他)非零数字。 因此,内部的do
循环退出,因为avail_out
不为零,并且我们尝试将更多数据放入next_in
和avail_in
,即使不是所有的avail_in
都已经处理过,因为avail_in
不为零。 这会破坏next_in
和avail_in
并且在下一次调用时inflate
失败。
我的解决方法是将内循环的终止条件从
strm.avail_out == 0
至
strm.avail_out == 0 || strm.avail_in > 0
但我不知道这是否正确。 我觉得这可能是miniz
的错误,但不确定。 我本以为如果avail_in
指示仍有数据要处理,则avail_out
必须为零。
如果相关,我正在使用的输入缓冲区大小为512KB,输出缓冲区为2MB。
如果inflate()
返回Z_OK
或Z_BUF_ERROR
,并且avail_out
不为零,则avail_in
为零 。
您可以提供有问题的压缩数据吗?
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.