zLib inflate()在解压缩缓冲区时挂起 [英] zLib inflate() hangs while uncompressing buffer

查看:730
本文介绍了zLib inflate()在解压缩缓冲区时挂起的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用的是zLib 1.2.7,摘自此处.我已经在Microsoft Visual Studio 2010中将其编译为静态库,并将其添加到我的项目中.

I use zLib 1.2.7, taken from here. I have compiled it in Microsoft Visual Studio 2010 as a static library and added it to my project.

我需要解压缩一些使用deflate算法压缩的二进制数据.在这里:

I need to decompress some binary data compressed with deflate algorithm. Here it is:

unsigned char rawData[114] =
{
    0x00, 0x00, 0x00, 0x00, 0x15, 0x82, 0x05, 0x9D, 0x62, 0x91, 0x9A, 0x86, 0x26, 0xF3, 0x45, 0xBF, 
    0xE1, 0x69, 0x19, 0xA8, 0x80, 0x21, 0x08, 0x43, 0xF1, 0xEF, 0xCC, 0x01, 0x68, 0x4E, 0x3C, 0x06, 
    0x59, 0x6D, 0x90, 0xB2, 0x1F, 0xC3, 0x87, 0xC2, 0xBF, 0xC0, 0x90, 0xBE, 0x1F, 0x11, 0xB6, 0xD7, 
    0xB7, 0x06, 0x18, 0x32, 0x5F, 0x80, 0x8F, 0x09, 0xF1, 0x81, 0xF2, 0xB8, 0xC8, 0x9E, 0x71, 0xB7, 
    0xC9, 0x73, 0x7E, 0x88, 0x02, 0xD0, 0x9C, 0x65, 0xB0, 0x34, 0xD3, 0x97, 0x33, 0xE8, 0x80, 0x2D, 
    0x09, 0xC6, 0x5B, 0x03, 0x4D, 0x39, 0x73, 0x74, 0x1B, 0xAD, 0x19, 0x9D, 0xF0, 0xCA, 0x6F, 0xBD, 
    0xA4, 0xD5, 0x33, 0x6E, 0xDF, 0x1F, 0x11, 0x8A, 0xC5, 0xA2, 0x1C, 0x99, 0xE2, 0xDB, 0xBF, 0x7C, 
    0x0E, 0x8B
};

此数据块是从 SPDY 捕获的会议.这是我的解压缩代码(SPDY_dictionary_txt可在上一个链接中找到):

This block of data was captured from SPDY session. And this is my uncompress code (SPDY_dictionary_txt can be found on previous link):

INT APIENTRY WinMain( __in HINSTANCE hInstance, __in_opt HINSTANCE hPrevInstance, __in LPSTR lpCmdLine, __in int nShowCmd )
{
    z_stream zStream = { 0 };
    DWORD Length = sizeof(rawData);

    zStream.zalloc = Z_NULL;
    zStream.zfree  = Z_NULL;
    zStream.opaque = Z_NULL;

    inflateInit(&zStream);

    zStream.avail_in = Length;
    zStream.next_in = rawData;

    DWORD dwUsed = 0;
    DWORD dwSize = 5 * 1024;
    LPBYTE lpDecompressed = NULL;
    BOOL triedDictionary = FALSE;
    BOOL uncompressed = TRUE;

    lpDecompressed = (LPBYTE)calloc(dwSize, 1);

    do
    {
        zStream.next_out = (LPBYTE)((DWORD_PTR)lpDecompressed + dwUsed);
        zStream.avail_out = dwSize - dwUsed;

        int zlib_rv = inflate(&zStream, Z_NO_FLUSH); // <-- THIS HANGS!

        if (zlib_rv == Z_NEED_DICT) 
        {
            if (triedDictionary)
            {
                uncompressed = FALSE;
                break;
            }

            triedDictionary = TRUE;
            inflateSetDictionary(&zStream, SPDY_dictionary_txt, sizeof(SPDY_dictionary_txt));
        }

        if (zlib_rv < 0)
        {
            uncompressed = FALSE;
            break;
        }

        dwUsed += dwSize - dwUsed - zStream.avail_out;
    }
    while (zStream.avail_in);

    if(!uncompressed)
    {
        OutputDebugString("Could not decompress buffer.\n");
    }
    else
    {
        OutputDebugString("Buffer was decompressed.\n");
    }

    Sleep(1000);

    return 0;
}

我开始调试此代码,发现它挂在第一个inflate()调用上.这是什么?这是zLib中的错误,还是我的代码错误?

I started to debug this code and found out that it hangs on the first inflate() call. What is this? Is this a bug in zLib or maybe my code is wrong?

推荐答案

您下载的代码不是原始的zlib代码.有人对其进行了修改,以编译没有警告和错误",并且可能在此过程中引入了错误.您需要从 zlib.net 下载原始且正确的代码.例如,您下载的代码在2014年5月31日提交,日志消息为在inflate.c和infback.c中纠正了无限循环错误".在从陌生人那里下载代码时,您应该格外小心.

The code you downloaded is not the original zlib code. It was modified by someone to compile "without warnings and errors" and bugs may have been introduced in the process. You need to download the original and correct code from zlib.net. The code you downloaded has, for example, a commit on May 31, 2014 with the log message "Corrected infinite loop errors in inflate.c and infback.c". You should be more careful about downloading code from strangers.

请注意,问题中提供的数据不是zlib压缩的结果,并且在读取前两个字节时,inflate()将立即拒绝该数据,因为它们甚至都不是zlib头.您必须使用其他一些输入数据才能使代码挂起".您需要提供引起问题的实际数据,以便任何人都能为您提供帮助.

Note that the data provided in the question is not the result of zlib compression, and would be immediately rejected by inflate() upon reading the first two bytes as not even being a zlib header. You must be using some other input data to get your code to "hang". You need to provide the actual data that caused the issue in order for anyone to be able to help you.

关于您的代码:您无需像在执行操作那样在循环内更新next_outavail_out,因为inflate()已经这样做了.当循环以dwSize - zStream.avail_out退出时,您可以计算dwUsed.您还需要检查inflate()中的返回码,以确保完成后返回Z_STREAM_END,否则流不完整.您不应在Z_BUF_ERROR上中止,而应提供更多的输出空间或更多的输入.有关如何使用inflate()deflate()的信息,请参见此示例,并阅读

About your code: you do not need to update next_out and avail_out inside the loop as you are doing, since inflate() already does that. You can compute dwUsed when the loop exits as dwSize - zStream.avail_out. You also need to check the return code from inflate() to make sure that it returns Z_STREAM_END when done, otherwise the stream was not complete. You should not abort on Z_BUF_ERROR, but rather provide more output space or more input. See this example for how inflate() and deflate() are used, and read the documentation in zlib.h.

这篇关于zLib inflate()在解压缩缓冲区时挂起的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆