zlib:解压缩数据时出现错误 -3:距离太远无效
zlib: Error -3 while decompressing data: invalid distance too far back
我正在尝试将代码写入 write/read MS-ZIP 压缩的 CAB 文件。 MS-ZIP 使用在 zlib 中实现的相同压缩算法。我已将问题简化为这个仅涉及 zlib 的简单脚本。
我知道压缩功能是正确的,因为其他CAB提取工具可以读取以这种方式生成的文件。
解压缩功能不工作。当必须解压缩超过 1 个块时,它会失败。
无法正确获取与压缩码匹配的解压码
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
它在 ideone.com http://ideone.com/baD3gg 上也失败了,它是 运行ning python 3.4.3+ zlib 1.2.8
我似乎 运行 陷入了 CPython 问题 #27164。在我撰写本文时 (2016-11-21),仅在 master 和 3.5 分支中提供了修复程序。
我正在尝试将代码写入 write/read MS-ZIP 压缩的 CAB 文件。 MS-ZIP 使用在 zlib 中实现的相同压缩算法。我已将问题简化为这个仅涉及 zlib 的简单脚本。
我知道压缩功能是正确的,因为其他CAB提取工具可以读取以这种方式生成的文件。
解压缩功能不工作。当必须解压缩超过 1 个块时,它会失败。
无法正确获取与压缩码匹配的解压码
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
它在 ideone.com http://ideone.com/baD3gg 上也失败了,它是 运行ning python 3.4.3+ zlib 1.2.8
我似乎 运行 陷入了 CPython 问题 #27164。在我撰写本文时 (2016-11-21),仅在 master 和 3.5 分支中提供了修复程序。