[英]What guarantees does zlib's inflate/deflate make about avail_in and avail_out?
What guarantees does zlib
give on the state of avail_in
an avail_out
after a call to inflate
? 没有什么保障
zlib
给出的状态avail_in
的avail_out
后调用inflate
? I am seeing peculiar behaviour with miniz
that I want to make sure is not a misunderstanding of the zlib
API. 我正在查看
miniz
特殊行为,我想确保这不是对zlib
API的误解。 Effectively, after calling inflate
, I have avail_in
non-zero, and avail_out
also non-zero, so some input looks like it is not getting processed. 实际上,打完电话后
inflate
,我已经avail_in
非零和avail_out
也非零,所以一些输入看起来是没有得到处理。 More details below. 下面有更多详细信息。
I have been using miniz to inflate/deflate a file I stream to/from disk. 我一直在使用miniz对从磁盘流到/从磁盘流过的文件进行膨胀/ 收缩 。 My inflate/deflate loop is identical to the zlib sample in zpipe.c , including using
MZ_NO_FLUSH
. 我的inflate / deflate循环与zpipe.c中的zlib示例相同,包括使用
MZ_NO_FLUSH
。
This loop has almost always worked, but today I inflated a stream deflated earlier and got an MZ_DATA_ERROR
consistently. 这个循环几乎一直都起作用,但是今天我膨胀了一个早先放气的流,并始终得到
MZ_DATA_ERROR
。 After adding the proper header though, gzip
was able to inflate it fine and my data was intact. 不过,在添加了适当的标头之后,
gzip
便可以对其进行良好的充气,并且我的数据是完整的。
The source of my issues came down to what would be the last call to mz_inflate
. 我问题的根源在于对
mz_inflate
的最后一次调用。 I include the typical inflate loop here: 我在这里包括典型的膨胀循环:
/* 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);
The inner do
loop repeats until all of the current chunk has been processed and avail_out
has extra room. 重复
do
内部do
循环,直到处理avail_out
所有当前块,并且avail_out
具有额外空间avail_out
。 However, on the last chunk of this particular stream, inflate
did not return an error, but rather would reduce avail_in
to some non-zero number, and would reduce avail_out
also to some (other) non-zero number. 然而,在这个特别的流的最后一块,
inflate
并没有返回错误,而是会降低avail_in
一些非零数字,并会减少avail_out
也给一些(其他)非零数字。 So the inner do
loop exits, as avail_out
is non-zero, and we go try and get more data into next_in
and avail_in
, even though not all of avail_in
has been processed, since avail_in
is non-zero. 因此,内部的
do
循环退出,因为avail_out
不为零,并且我们尝试将更多数据放入next_in
和avail_in
,即使不是所有的avail_in
都已经处理过,因为avail_in
不为零。 This clobbers whatever was in next_in
and avail_in
and the inflate
fails on the next call. 这会破坏
next_in
和avail_in
并且在下一次调用时inflate
失败。
My workaround was to change the inner loop's termination condition from 我的解决方法是将内循环的终止条件从
strm.avail_out == 0
to 至
strm.avail_out == 0 || strm.avail_in > 0
but I have no idea if this is correct. 但我不知道这是否正确。 I feel this may be a bug in
miniz
but am not sure. 我觉得这可能是
miniz
的错误,但不确定。 I would have thought that if avail_in
indicated there was still data to be processed, that avail_out
must be zero. 我本以为如果
avail_in
指示仍有数据要处理,则avail_out
必须为零。
In case it is relevant: the input buffer size I am using is 512KB and the output buffer is 2MB. 如果相关,我正在使用的输入缓冲区大小为512KB,输出缓冲区为2MB。
If inflate()
returns Z_OK
or Z_BUF_ERROR
, and avail_out
is not zero, then avail_in
is zero. 如果
inflate()
返回Z_OK
或Z_BUF_ERROR
,并且avail_out
不为零,则avail_in
为零 。
Can you provide the compressed data in question? 您可以提供有问题的压缩数据吗?
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.