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

GZIPInputStream (and InflaterStream?) does not support marking as claimed

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Fixed
    • Icon: P3 P3
    • 5.0
    • 1.2.1, 1.4.1
    • core-libs
    • tiger
    • x86, sparc
    • linux, solaris_7, windows_2000



      Name: nt126004 Date: 02/03/2003


      FULL PRODUCT VERSION :
      java version "1.4.1_01"
      Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.1_01-b01)
      Java HotSpot(TM) Client VM (build 1.4.1_01-b01, mixed mode)

      also:

      java version "1.4.0_01"
      Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.0_01-b03)
      Java HotSpot(TM) Client VM (build 1.4.0_01-b03, mixed mode)


      FULL OPERATING SYSTEM VERSION : Linux Red Hat 7.2/7.3 on
      Intel


      A DESCRIPTION OF THE PROBLEM :
      The markSupported() method of instances of class
      java.util.zip.GZIPInputStream returns 'true'. However, such
      instances do not correctly support the mark/reset methods as
      described in InputStream's general contract.

        From the source code, it looks like it is
      InflaterInputStream (GZIPInputStream's superclass) which is
      actually at fault here, but this bug is reported in terms of
      GZIPInputStream since I have a test case which demonstrates
      this manifestation of it.

      InflaterInputStream inherits behaviour from
      FilterInputStream, in which the markSupported, mark and
      reset methods are just passed on to the underlying stream.
      One can see how its authors failed to spot that this would
      be a problem - could be worth a note in the javadocs of the
      FilterInputStream markSupported, mark and/or reset methods
      to the effect that subclasses should be careful about
      inheriting this behaviour?

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      1. get a GZIPInputStream instance
      2. call mark(n) on it
      3. read n bytes from it into a buffer
      4. call reset() on it
      5. read n bytes into another buffer

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      The expected result is that the two buffers should have the
      same contents.
      In fact they have different contents (unless they match by
      luck).
      They should have the same since GZIPInputStream claims to
      support marking
      (markSupported returns true for GZIPInputStream instances).

      Alternatively, markSupported should return false for
      instances of GZIPInputStream.

      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------
      import java.io.ByteArrayInputStream;
      import java.io.ByteArrayOutputStream;
      import java.io.IOException;
      import java.io.InputStream;
      import java.io.OutputStream;
      import java.util.zip.GZIPInputStream;
      import java.util.zip.GZIPOutputStream;

      public class GzipBug {

          private static final int MAXBUF = 256;

          public static void main( String[] args ) throws IOException {

              /* Set up some buffers. */
              int nbyte = 6;
              byte[] buf1 = new byte[ nbyte ];
              byte[] buf2 = new byte[ nbyte ];

              /* Get a stream of gzipped data. */
              InputStream compressedStream = getGzippedDataStream();

              /* Get a gunzipped version. */
              InputStream reflatedStream = new GZIPInputStream( compressedStream );

              /* GZIPInputStream claims to support marks. */
              if ( reflatedStream.markSupported() ) {
                  System.out.println( reflatedStream +
                                      ".markSupported() = true" );
              }
              else {
                  System.out.println( reflatedStream +
                                      " does not claim to support marks - no bug" );
                  return;
              }

              /* Mark to allow re-read of nbyte bytes. */
              reflatedStream.mark( nbyte );

              /* Read nbyte bytes from start of stream into first buffer. */
              reflatedStream.read( buf1, 0, nbyte );

              /* Reset to mark position (start of stream). */
              reflatedStream.reset();

              /* Read nbyte bytes from start of stream into second buffer. */
              reflatedStream.read( buf2, 0, nbyte );

              /* Output data from the two buffers. Only the first is correct. */
              for ( int i = 0; i < nbyte; i++ ) {
                  System.out.println( Integer.toHexString( buf1[ i ] & 0xff ) + "\t"
                                    + Integer.toHexString( buf2[ i ] & 0xff ) );
              }
          }

          /**
           * Returns some arbitrary source of data bytes.
           */
          private static InputStream getDataStream() throws IOException {
              return Object.class.getResourceAsStream( "Object.class" );
          }

          /**
           * Returns an input stream containing a gzipped version of some
           * arbitrary data.
           */
          private static InputStream getGzippedDataStream() throws IOException {
              byte[] zbuf;
              ByteArrayOutputStream bstrm = new ByteArrayOutputStream();
              OutputStream zstrm = new GZIPOutputStream( bstrm );
              InputStream istrm = getDataStream();
              byte[] buf = new byte[ MAXBUF ];
              for ( int nbyte; (nbyte = istrm.read( buf )) > 0; ) {
                  zstrm.write( buf, 0, nbyte );
              }
              istrm.close();
              zstrm.close();
              zbuf = bstrm.toByteArray();
              return new ByteArrayInputStream( zbuf );
          }
      }

      ---------- END SOURCE ----------

      CUSTOMER WORKAROUND :
      You can wrap the GZIPInputStream in a BufferedInputStream,
      or subclass it so that its markSupported method returns
      false.
      Or just not use mark/reset.
      (Review ID: 180523)
      ======================================================================

            mmcclosksunw Michael Mccloskey (Inactive)
            nthompsosunw Nathanael Thompson (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: