JDK-4795134 : InflaterInputStream.available returns 1 at end of stream
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.util.jar
  • Affected Version: 1.2.1,1.4.1
  • Priority: P4
  • Status: Closed
  • Resolution: Not an Issue
  • OS: solaris_7,windows_2000
  • CPU: x86,sparc
  • Submitted: 2002-12-17
  • Updated: 2006-12-14
  • Resolved: 2006-12-14
Related Reports
Relates :  
Description
Name: nt126004			Date: 12/17/2002


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

(Also happens in 1.4.1_01)

FULL OPERATING SYSTEM VERSION :

Microsoft Windows 2000 [Version 5.00.2195]

ADDITIONAL OPERATING SYSTEMS :

All

A DESCRIPTION OF THE PROBLEM :
InflaterInputStream.available method can return 1 even
though there is nothing more to be read.

If the reader of InflaterInputStream reaches the exact end
of the stream, without trying to read past the end, the
InflaterInputStream will not realize that the stream is
empty and will still report that byte(s) are available.


The "available" contract is:

1. Don't return more bytes than are available.
2. Don't return more bytes than can be read without blocking.

The InflaterInputStream implementation fails on count #1.


STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. Run the test program below.


EXPECTED VERSUS ACTUAL BEHAVIOR :
Test program deflates some bytes and reads them back into
the same buffer. At this point, the input stream is empty
but it still reports that at least one byte is available.

The program below reproduces the bug and reports:

  "java.io.IOException: available = 1, read = -1"

Note that available() returns 1 but the next read() fails.

The expected result is that available will return 0 when
there are no more bytes to be read.


ERROR MESSAGES/STACK TRACES THAT OCCUR :
When debugging this, I observed that the InflaterInputStream had not detected
readEOF even though the Inflater itself knew it was finished.

Beware: ZipFile's Inflater's "finished" flag never appears to get set.


REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
/*
 * InflaterAvailableTest.java
 */

import java.io.*;
import java.util.zip.*;

/**
 * Demonstrates bug in InflaterInputStream.available
 * method, where available returns 1 even though there
 * is nothing more to be read.
 *
 * @author  joe.bowbeer
 */
public class InflaterAvailableTest {
    
    /**
     * Deflate some bytes and read them back into the
     * same buffer. At this point, the input stream is
     * empty but it still reports that at least one byte
     * is available.
     */
    public static void main(String[] args)
    throws Exception {
        byte[] data = new byte[42];
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        DeflaterOutputStream dos = new DeflaterOutputStream(baos);
        dos.write(data);
        dos.close();
        ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
        InflaterInputStream iis = new InflaterInputStream(bais);
        DataInputStream dais = new DataInputStream(iis);
        dais.readFully(data);
        int available = dais.available();
        if (available > 0) {
            throw new IOException(
                "available = " + available + ", " +
                "read = " + dais.read());
        }
    }
}

---------- END SOURCE ----------
(Review ID: 178892) 
======================================================================

Comments
EVALUATION The original Description says: > The "available" contract is: > > 1. Don't return more bytes than are available. but that's not *quite* right; available() returns an *estimate*. The javadoc of InflaterInputStream.available() says: > Returns 0 after EOF has been reached, otherwise always return 1. This has been the case since the available() method was introduced.
14-12-2006

EVALUATION We can't make available() return the number of bytes available in this case and if we could, it would be an incompatible change. ###@###.### 2002-12-17 Investigating this further. If there is a compatible change then it may be considered for Tiger. ###@###.### 2003-01-06 We have reconsidered and discovered a way to detect when there is no more data available to improve the method's accuracy in certain cases. ###@###.### 2003-02-07 This fix is flawed in that it depends upon certain types of input streams to be used. Since there is no such guarantee this fix will be taken out. See 4868205. ###@###.### 2003-05-23
23-05-2003