Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8081450

GZIPInputStream prematurely infers end-of-stream

    XMLWordPrintable

Details

    Description

      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.

      Attachments

        Issue Links

          Activity

            People

              acobbs Archie Cobbs
              webbuggrp Webbug Group
              Votes:
              0 Vote for this issue
              Watchers:
              5 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved: