2011-03-11 6 views
10

내 gzip 디코딩 코드 중 일부가 손상된 데이터를 감지하지 못하는 것으로 나타났습니다. Java GZipInputStream 클래스에서이 문제를 추적했다고 생각합니다. 특히, 단일 '읽기'호출로 전체 스트림을 읽을 때 손상된 데이터가 IOException을 유발하지 않는 것으로 보입니다. 동일한 손상된 데이터에서 둘 이상의 호출로 스트림을 읽으면 예외가 트리거됩니다.Java GZipInputStream 클래스의 버그입니까?

버그 보고서를 제출하기 전에 커뮤니티가 생각한 것을보고 싶었습니다.

편집 : 마지막 예제는 내가 문제로 인식하는 것을 분명하게 보여주지 않았기 때문에 예제를 수정했습니다. 이 새로운 예제에서는 10 바이트 버퍼가 gzip되고, gzipped 버퍼의 1 바이트가 수정 된 다음 ungzipped입니다. 'GZipInputStream.read'에 대한 호출은 읽은 바이트의 수를 10으로 반환합니다. 이는 10 바이트 버퍼에 대해 예상 한 것입니다. 그럼에도 압축 해제 된 버퍼는 원본과 다릅니다 (손상으로 인해). 예외는 발생하지 않습니다. 나는 EOF에 도달했을 때 '0'대신 '1'을 반환 한 후 'available'을 호출하는 것을 주목했습니다.

당신이 놓친 것 :

@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 좋은 질문; 자급 자족, 간결한, 실행 가능한 예제로 잘 작성되었습니다. 이것이 바로 당신이 그런 빠른 대답을 얻은 이유입니다 :-) –

답변

9

이 테스트를 실행하기로 결정 여기

는 소스입니다. gis.read(unzipped)은 1을 반환하므로 1 바이트 만 읽습니다. 불평 할 수는 없으며 스트림의 끝이 아닙니다.

다음 read()"손상된 GZIP 예고편"을 던집니다.

이렇게 좋습니다! (그리고 버그가 없습니다. 최소한 GZIPInputStream)

+0

+1 나를 때려 눕히기 :-) 적어도 재미있게 JDK에서 파고 들었습니다 :-) –

+0

실제로 나는 코드를 보았을 때 무슨 일이 일어나는지 99 % 이상 확신했습니다. . byte [] {0,0, -1, -1}은 Z_SYNC_FLUSH의 표시이므로, 그가 맞았을 것이라고 생각했습니다. – bestsss

+0

GZIPInputStream을 사용한 적이 없으므로 추적해야했습니다. 나는 열쇠가 부패가 트레일러가 아니라 데이터에 있다고 생각한다. –