zLib inflate()在解压缩缓冲区时挂起

时间:2015-03-20 11:09:55

标签: zlib inflate spdy

我使用zLib 1.2.7,取自here。我已将它作为静态库在Microsoft Visual Studio 2010中编译并将其添加到我的项目中。

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

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可以在以前的链接中找到):

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中的错误还是我的代码错了?

1 个答案:

答案 0 :(得分:3)

您下载的代码不是原始的zlib代码。它被某人修改为编译&#34;没有警告和错误&#34;并且可能已在此过程中引入了错误。您需要从zlib.net下载原始且正确的代码。例如,您下载的代码在2014年5月31日提交了日志消息&#34;更正了inflate.c和infback.c中的无限循环错误&#34;。从陌生人处下载代码应该更加小心。

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

关于您的代码:您不需要在循环中更新next_outavail_out,因为inflate()已经这样做了。当循环退出为dwUsed时,您可以计算dwSize - zStream.avail_out。您还需要检查inflate()的返回码,以确保它在完成时返回Z_STREAM_END,否则流不完整。您不应该在Z_BUF_ERROR上中止,而是提供更多输出空间或更多输入。有关inflate()deflate()的使用方式,请参阅this example,并阅读documentation in zlib.h