简体   繁体   English

zlib对avail_in和avail_out的充气/放气有什么保证?

[英]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_inavail_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_inavail_in ,即使不是所有的avail_in都已经处理过,因为avail_in不为零。 This clobbers whatever was in next_in and avail_in and the inflate fails on the next call. 这会破坏next_inavail_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_OKZ_BUF_ERROR ,并且avail_out 为零,则avail_in 为零

Can you provide the compressed data in question? 您可以提供有问题的压缩数据吗?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM