2011-03-11 12 views
10

Me di cuenta de que parte de mi código de decodificación gzip parecía no detectar datos corruptos. Creo que he rastreado el problema hasta la clase Java GZipInputStream. En particular, parece que cuando lee toda la secuencia con una sola llamada de "lectura", los datos dañados no desencadenan una IOException. Si lee la secuencia en 2 o más llamadas en la misma información corrupta, entonces activa una excepción.¿Es esto un error en la clase Java GZipInputStream?

Quería ver qué pensaba la comunidad aquí antes de considerar la presentación de un informe de error.

EDITAR: He modificado mi ejemplo porque el último no ilustró tan claramente lo que percibo como el problema. En este nuevo ejemplo, se almacena un búfer de 10 bytes, se modifica un byte del búfer gzip y luego se descomprime. La llamada a 'GZipInputStream.read' devuelve 10 como la cantidad de bytes leídos, que es lo que esperaría para un buffer de 10 bytes. Sin embargo, el buffer descomprimido es diferente al original (debido a la corrupción). No se arroja ninguna excepción. Observé que al llamar 'disponible' después de la lectura, se devuelve '1' en lugar de '0', que sería si se hubiera alcanzado el EOF.

Aquí está la fuente:

@Test public void gzip() { 
    try { 
     int length = 10; 
     byte[] bytes = new byte[]{12, 19, 111, 14, -76, 34, 60, -43, -91, 101}; 
     System.out.println(Arrays.toString(bytes)); 

     //Gzip the byte array 
     ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
     GZIPOutputStream gos = new GZIPOutputStream(baos); 
     gos.write(bytes); 
     gos.finish(); 
     byte[] zipped = baos.toByteArray(); 

     //Alter one byte of the gzipped array. 
     //This should be detected by gzip crc-32 checksum 
     zipped[15] = (byte)(0); 

     //Unzip the modified array 
     ByteArrayInputStream bais = new ByteArrayInputStream(zipped); 
     GZIPInputStream gis = new GZIPInputStream(bais); 
     byte[] unzipped = new byte[length]; 
     int numRead = gis.read(unzipped); 
     System.out.println("NumRead: " + numRead); 
     System.out.println("Available: " + gis.available()); 

     //The unzipped array is now [12, 19, 111, 14, -80, 0, 0, 0, 10, -118]. 
     //No IOException was thrown. 
     System.out.println(Arrays.toString(unzipped)); 

     //Assert that the input and unzipped arrays are equal (they aren't) 
     org.junit.Assert.assertArrayEquals(unzipped, bytes); 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } 
    } 
+1

+1 buena pregunta; bien escrito, con un ejemplo autónomo, conciso, RUNNABLE. Esta es la razón por la que obtuviste una respuesta tan rápida :-) –

Respuesta

9

decidió correr la prueba:

Lo que no se ha contestado. gis.read(unzipped) devuelve 1, por lo que ha leído solo un byte. No puede quejarse, no es el final de la transmisión.

El siguiente read() arroja "Corrupto GZIP corrupto".

¡Así que todo está bien! (y no hay errores, al menos en GZIPInputStream)

+0

+1 Me ganaste :-) Al menos me divertí hurgando en el JDK :-) –

+0

en realidad estaba más del 99% seguro de lo que sucede cuando vi el código . byte [] {0,0, -1, -1} es la marca de Z_SYNC_FLUSH, así que pensó que podría haberlo golpeado. – bestsss

+0

Nunca he usado GZIPInputStream, así que tuve que rastrearlo. Creo que la clave es que la corrupción estaba en el trailer y no en los datos. –

Cuestiones relacionadas