zlib:解压数据时错误-3:无效距离过远



我正在尝试编写代码来写入/读取MS-ZIP压缩CAB文件。MS-ZIP使用在zlib中实现的相同deflate算法。我已经把这个问题简化为这个简单的脚本,它只涉及到zlib。

  • 我知道压缩功能是正确的,因为其他CAB提取工具可以读取文件产生这种方式

  • 解压功能不工作。

我无法获得与压缩代码匹配的解压缩代码。

import sys, struct, zlib
MAX_CHUNK_SIZE = 100
def main():
    uncomp = (b'GQOLELNFJH@?AQE@LBA=?@N@<GJHE=EGE<FQOAM@?<IABT>EK'
              b'<=QFRPBSRGFRENSJLDFGD=LSRHIAO?FB@NP?DGDS>NGT@CCFPS'
              b'A@B=IGG<?JQBGBPLOPONU?IBBSNBK<QAFLGK@>H=CQ?BS><@UE'
              b'QGAKHML@>?JOSEQRCTP>S<?N>DNM@??ARJ>QUJSHLQN<P<>D==')
    print("python", sys.version)
    print("zlib version", zlib.ZLIB_VERSION)
    print("zlib runtime version", zlib.ZLIB_RUNTIME_VERSION)
    chunks = compress(uncomp)
    decomp = decompress(chunks)
    assert(uncomp == decomp)

def compress(data):
    start_off = 0
    data_size = len(data)
    remaining = data_size
    res = []
    zdict = b''
    while start_off < data_size:
        print("compress chunk %d"%len(res))
        chunk_size = min(MAX_CHUNK_SIZE, remaining)
        chunk = data[start_off:start_off+chunk_size]
        c = b''
        z = zlib.compressobj(wbits=-15, zdict=zdict)
        c += z.compress(chunk)
        c += z.flush(zlib.Z_FINISH)
        res.append(c)
        zdict = chunk
        start_off += chunk_size
        remaining -= chunk_size
    return res
def decompress(chunks):
    zdict = b''
    res = []
    for i, c in enumerate(chunks):
        print("decompress chunk %d"%i)
        out = b''
        z = zlib.decompressobj(wbits=-15, zdict=zdict)
        out += z.decompress(c)
        out += z.flush()
        zdict = out
        res.append(out)
    return b''.join(res)

if __name__ == '__main__':
    main()

当我运行这个脚本时,我得到:

python 3.4.5 (default, Jul 03 2016, 13:55:08) [GCC]
zlib version 1.2.8
zlib runtime version 1.2.8
compress chunk 0
compress chunk 1
decompress chunk 0
decompress chunk 1
Traceback (most recent call last):
  File "bug.py", line 65, in <module>
    main()
  File "bug.py", line 16, in main
    decomp = decompress(chunks)
  File "bug.py", line 55, in decompress
    out += z.decompress(c)
zlib.error: Error -3 while decompressing data: invalid distance too far back

在运行python 3.4.3+ zlib 1.2.8的ideone.com http://ideone.com/baD3gg上也失败

似乎我遇到了CPython问题#27164。在我写这篇文章的时候(2016-11-21),一个修复只在分支master和3.5中可用。

https://bugs.python.org/issue27164

最新更新