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 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 :-) –