JDK-6631046 : BufferedInputStream.available() reports negative int on very large inputstream
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.io
  • Affected Version: 6
  • Priority: P3
  • Status: Closed
  • Resolution: Fixed
  • OS: linux
  • CPU: x86
  • Submitted: 2007-11-16
  • Updated: 2011-03-07
  • Resolved: 2011-03-07
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 7
7 b121Fixed
Related Reports
Relates :  
Description
FULL PRODUCT VERSION :
$ java -version
java version "1.6.0_03"
Java(TM) SE Runtime Environment (build 1.6.0_03-b05)
Java HotSpot(TM) Server VM (build 1.6.0_03-b05, mixed mode)


ADDITIONAL OS VERSION INFORMATION :
$ uname -a
Linux david 2.6.22-14-generic #1 SMP Sun Oct 14 23:05:12 GMT 2007 i686 GNU/Linux
kfc@david:~$ java -version


A DESCRIPTION OF THE PROBLEM :
InputStream.available() returns an int. For streams larger than 2GB this might be a problem, and a reasonable choice is to return Integer.MAX_VALUE in that case. This is the behavior of FileInputStream().

However, a stream with this behaviour will malfunction if wrapped in a BufferedInputStream, since the implementation if "available()" in BufferedInputStream.available() returns in.available() + (count - pos), which will give an overflow and return a negative size.

This is the implementation of BufferedInputStream.available():

    public synchronized int available() throws IOException {
	return getInIfOpen().available() + (count - pos);
    }


STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Make a 3 GB file "x.foo".

Run the test program below.


EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Same behaviour on buffered and unbuffered inputstream:
Integer.MAX_VALUE returned in all cases.

FileInputStream:
2147483647
2147483647
BufferedInputStream:
2147483647
2147483647
ACTUAL -
Negative results from BufferedOutputStream

FileInputStream:
2147483647
2147483647
BufferedInputStream:
2147483647
-2147475458

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
// Assumes existence of a 3 GB file "x.foo".

import java.io.*;

public class X {
    public static void main(String... args) throws Exception {
        System.out.println("FileInputStream:");
        InputStream is = new FileInputStream("x.foo");
        System.out.println(is.available());
        is.read();
        System.out.println(is.available());

        System.out.println("BufferedInputStream:");
        is = new BufferedInputStream(new FileInputStream("x.foo"));
        System.out.println(is.available());
        is.read();
        System.out.println(is.available());
    }
}
---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
Make a subclass of BufferedInputStream and override available(). Only possible if you are in charge of the InputStreams you receive.

Comments
EVALUATION Changeset URL: http://hg.openjdk.java.net/jdk7/tl/jdk/rev/f30e1e1a4d90
19-11-2010

EVALUATION BufferedInputStream.available() should return Integer.MAX_VALUE when the number of bytes available to be read exceeds Integer.MAX_VALUE as FileInputStream.available() returns. The implementation of PushbackInputStream.available() also has to be fixed to handle overflow.
10-11-2010

EVALUATION FileInputStream.available() has similar problems as described in 6402006. Both of theses bugs should be examined/fixed simultaneously. Note also that it would be prudent to examine all of the available() methods in this package for similar issues.
25-01-2008