United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
Bug ID: JDK-4812237 GZIPInputStream (and InflaterStream?) does not support marking as claimed
JDK-4812237 : GZIPInputStream (and InflaterStream?) does not support marking as claimed

Details
Type:
Bug
Submit Date:
2003-02-03
Status:
Resolved
Updated Date:
2003-05-16
Project Name:
JDK
Resolved Date:
2003-05-16
Component:
core-libs
OS:
solaris_7,linux,windows_2000
Sub-Component:
java.util.jar
CPU:
x86,sparc
Priority:
P3
Resolution:
Fixed
Affected Versions:
1.2.1,1.4.1
Fixed Versions:
5.0 (tiger)

Related Reports
Duplicate:

Sub Tasks

Description

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) 
======================================================================

                                    

Comments
EVALUATION

markSupported should return false for instances of GZIPInputStream. The compatibility impact of this should be examined. I am committing to Tiger.
###@###.### 2003-02-04
                                     
2003-02-04
CONVERTED DATA

BugTraq+ Release Management Values

COMMIT TO FIX:
tiger

FIXED IN:
tiger

INTEGRATED IN:
tiger
tiger-b07


                                     
2004-06-14



Hardware and Software, Engineered to Work Together