-
Bug
-
Resolution: Duplicate
-
P4
-
8u45, 9
-
x86_64
-
linux
FULL PRODUCT VERSION :
java version "1.8.0_45"
Java(TM) SE Runtime Environment (build 1.8.0_45-b14)
Java HotSpot(TM) 64-Bit Server VM (build 25.45-b02, mixed mode)
ADDITIONAL OS VERSION INFORMATION :
OS independent (Linux, Darwin, Windows)
A DESCRIPTION OF THE PROBLEM :
GZIPInputStream can decide that it hasn't reached end-of-stream (and stop processing input data) before a read of the underlying input stream has ever returned -1. This shouldn't be possible, because it can never know whether or not there will be another GZIP member (<header><compressed data><trailer>) in the input until the underlying stream has reported that there is no more data (by returning -1 from read).
Note that GZIPInputStream can, under many circumstances, handle concatenated gzip files just fine. But there are some circumstances, as in the example below, where it fails to do so.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Compile and run the code provided.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
hello world
ACTUAL -
hello
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
import java.io.*;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
public class GZIPInputBug {
public static void main(String[] args) {
try {
byte[] part1 = zip(stream("hello ".getBytes()));
byte[] part2 = zip(stream("world".getBytes()));
InputStream zippedData = new SequenceInputStream(stream(part1), stream(part2));
byte[] data = unzip(zippedData);
System.out.println(new String(data));
}
catch (IOException x) {
x.printStackTrace();
}
}
private static InputStream stream(byte[] data) {
return new ByteArrayInputStream(data);
}
private static byte[] zip(InputStream data) throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
GZIPOutputStream zout = new GZIPOutputStream(out);
copy(data, zout);
data.close();
zout.close();
return out.toByteArray();
}
private static byte[] unzip(InputStream zippedData) throws IOException {
GZIPInputStream zin = new GZIPInputStream(zippedData);
ByteArrayOutputStream out = new ByteArrayOutputStream();
copy(zin, out);
zin.close();
out.close();
return out.toByteArray();
}
private static void copy(InputStream source, OutputStream sink) throws IOException {
byte[] buf = new byte[4096];
int n;
while ((n = source.read(buf)) > 0) {
sink.write(buf, 0, n);
}
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
There is no easy or convenient workaround.
java version "1.8.0_45"
Java(TM) SE Runtime Environment (build 1.8.0_45-b14)
Java HotSpot(TM) 64-Bit Server VM (build 25.45-b02, mixed mode)
ADDITIONAL OS VERSION INFORMATION :
OS independent (Linux, Darwin, Windows)
A DESCRIPTION OF THE PROBLEM :
GZIPInputStream can decide that it hasn't reached end-of-stream (and stop processing input data) before a read of the underlying input stream has ever returned -1. This shouldn't be possible, because it can never know whether or not there will be another GZIP member (<header><compressed data><trailer>) in the input until the underlying stream has reported that there is no more data (by returning -1 from read).
Note that GZIPInputStream can, under many circumstances, handle concatenated gzip files just fine. But there are some circumstances, as in the example below, where it fails to do so.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Compile and run the code provided.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
hello world
ACTUAL -
hello
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
import java.io.*;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
public class GZIPInputBug {
public static void main(String[] args) {
try {
byte[] part1 = zip(stream("hello ".getBytes()));
byte[] part2 = zip(stream("world".getBytes()));
InputStream zippedData = new SequenceInputStream(stream(part1), stream(part2));
byte[] data = unzip(zippedData);
System.out.println(new String(data));
}
catch (IOException x) {
x.printStackTrace();
}
}
private static InputStream stream(byte[] data) {
return new ByteArrayInputStream(data);
}
private static byte[] zip(InputStream data) throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
GZIPOutputStream zout = new GZIPOutputStream(out);
copy(data, zout);
data.close();
zout.close();
return out.toByteArray();
}
private static byte[] unzip(InputStream zippedData) throws IOException {
GZIPInputStream zin = new GZIPInputStream(zippedData);
ByteArrayOutputStream out = new ByteArrayOutputStream();
copy(zin, out);
zin.close();
out.close();
return out.toByteArray();
}
private static void copy(InputStream source, OutputStream sink) throws IOException {
byte[] buf = new byte[4096];
int n;
while ((n = source.read(buf)) > 0) {
sink.write(buf, 0, n);
}
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
There is no easy or convenient workaround.
- duplicates
-
JDK-7036144 GZIPInputStream readTrailer uses faulty available() test for end-of-stream
- Closed