2016-11-17 3 views
1

J'essaye d'écrire du code pour écrire/lire des fichiers CAB compressés MS-ZIP. MS-ZIP utilise le même algorithme de dégonflement implémenté dans zlib. J'ai simplifié le problème à ce script simple qui ne concerne que zlib.zlib: Erreur -3 lors de la décompression des données: distance invalide trop loin

  • Je sais que la fonction de compression est correcte car d'autres outils d'extraction CAB peuvent lire les fichiers de cette façon.

  • La fonction de décompression ne fonctionne pas. Il échoue lorsque plus d'un bloc doit être décompressé.

Je ne peux pas obtenir le code de décompression correspondant au code de compression.

import sys, struct, zlib 

MAX_CHUNK_SIZE = 100 

def main(): 
    uncomp = (b'[email protected][email protected][email protected]@<GJHE=EGE<[email protected]?<IABT>EK' 
       b'<[email protected]?DGDS>[email protected]' 
       b'[email protected]=IGG<?JQBGBPLOPONU?IBBSNBK<[email protected]>H=CQ?BS><@UE' 
       b'[email protected]>?JOSEQRCTP>S<?N>[email protected]??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() 

Quand je lance ce script, je reçois:

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 

Il échoue également sur ideone.com http://ideone.com/baD3gg qui est en cours d'exécution python 3.4.3+ zlib 1.2.8

+0

Je viens de copier et collais votre code, il a couru et a obtenu 'RÉSULTATS 12/12 OK'. –

+1

(wow, salut Mark !!) Je reçois systématiquement ces erreurs (tests 5,6,7,8,9,10,11 parfois 2, 3). Exécuter zlib 1.2.8. J'ai essayé de vider les données et de les décompresser avec un programme C, les mêmes résultats que le script python (également lié à 1.2.8) éditeront mon post avec plus de code. – knarf

+0

J'ai modifié le post. – knarf

Répondre

1

Il semble que j'étais en cours d'exécution dans CPython numéro # 27164. Au moment où j'écris ceci (2016-11-21), un correctif est disponible dans les branches master et 3.5 uniquement.

https://bugs.python.org/issue27164

+0

En effet la version de python que j'ai est 3.5.2. J'ai obtenu: 'python 3.5.2 (v3.5.2: 4def2a2901a5, 26 juin 2016, 10:47:25) [GCC 4.2.1 (Apple Inc. build 5666) (point 3)] zlib version 1.2.3 zlib runtime version 1.2.8 comprimer le bloc 0 comprimer le bloc 1 décompress morceau 0 décompress morceau 1' –