Name: saC57035 Date: 12/01/98
java.util.zip.InflaterInputStream.read(b,off,len) doesn't throw IndexOutOfBoundsException
if either len or off parameter is negative in JDK-1.2fcs.
java.util.zip.ZipInputStream.read(b,off,len), java.util.zip.GZIPInputStream.read(b,off,len),
java.util.jar.JarInputStream.read(b,off,len) also inherit this incorrect behavior
in JDK-1.2fcs.
The general contract for the read method (see JLS item 22.3.3) clearly states:
"22.3.3 public int read(byte[] bytes, int offset,
int length) throws IOException,
NullPointerException, IndexOutOfBoundsException
< skipped >
If off is negative, or len is negative, or off+len is greater than the
length of the array b, then an IndexOutOfBoundsException is
thrown."
An example to check the following methods :
java.util.zip.InflaterInputStream.read(b,off,len),
java.util.zip.GZIPInputStream.read(b,off,len),
java.util.zip.ZipInputStream.read(b,off,len),
java.util.jar.JarInputStream.read(b,off,len)
being called with incorrect off, len:
===== Test10.java ========
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.util.zip.*;
import java.util.jar.*;
public class Test10 {
static final String manifestStream =
"Manifest-Version: 1.0\n\n"+
"Name: javasoft/sqe/javatest/lib/apitest/AssertionTest.class\n"+
"Digest-Algorithms: MD5, SHA\n"+
"MD5-Digest: edwjehdgwjedgwj\n"+
"SHA-Digest: eqweqweqwe\n\n"+
"Name: javasoft/sqe/javatest/lib/apitest/AssertionTest$ExpectedException.class\n\n"+
"Name: javasoft/sqe/javatest/lib/apitest/AssertionTest$ExceptionSet.class\n\n"+
"Name: javasoft/sqe/javatest/lib/apitest/AssertionTest$Fault.class\n\n"+
"Name: javasoft/sqe/javatest/lib/apitest/Factory.class\n\n"+
"Name: javasoft/sqe/javatest/lib/apitest/ImmutableObjectFactory.class\n\n"+
"Name: javasoft/sqe/javatest/lib/apitest/Generator.class\n\n"+
"Name: javasoft/sqe/javatest/lib/apitest/GridGenerator.class\n\n"+
"Name: javasoft/sqe/javatest/lib/apitest/SingletonGenerator.class\n\n"+
"Name: javasoft/sqe/javatest/lib/apitest/PrintReporter.class\n\n"+
"Name: javasoft/sqe/javatest/lib/apitest/Reporter.class\n\n"+
"Name: javasoft/sqe/javatest/lib/apitest/SummaryReporter.class";
public static void close (OutputStream os) {
try {
os.close();
} catch (java.io.IOException e) {
throw new RuntimeException("Unexpected "+e);
}
}
public static boolean readTest (InputStream is) {
byte[] b = new byte[200];
int a;
boolean passed = true;
for(int j=0;j<b.length;j++) b[j] = (byte)(j+3); // Fill input data array somehow
try {
try { //CASE 1
is.read(b, 0, -100); //len negative
System.out.println( "CASE1: Failed - IndexOutOfBoundsException is not thrown" );
passed = false;
}
catch(IndexOutOfBoundsException ib) {
System.out.println( "CASE1: OK - IndexOutOfBoundsException thrown" );
}
try { //CASE 2
is.read(b, 190, Integer.MIN_VALUE);
System.out.println( "CASE2: Failed - IndexOutOfBoundsException is not thrown" );
passed = false;
}
catch(IndexOutOfBoundsException ib) {
System.out.println( "CASE2: OK - IndexOutOfBoundsException thrown" );
}
try { //CASE 3
is.read(b, 0, 500); //len+off > b.length
System.out.println( "CASE3: Failed - IndexOutOfBoundsException is not thrown" );
passed = false;
}
catch(IndexOutOfBoundsException ib) {
System.out.println( "CASE3: OK - IndexOutOfBoundsException thrown" );
}
try { //CASE 4
is.read(b, -100, 0); //off negative
System.out.println( "CASE4: Failed - IndexOutOfBoundsException is not thrown" );
passed = false;
}
catch(IndexOutOfBoundsException ib) {
System.out.println( "CASE4: OK - IndexOutOfBoundsException thrown" );
}
try { //CASE 5
is.read(b, Integer.MIN_VALUE, 10);
System.out.println( "CASE5: Failed - IndexOutOfBoundsException is not thrown" );
passed = false;
}
catch(IndexOutOfBoundsException ib) {
System.out.println( "CASE5: OK - IndexOutOfBoundsException thrown" );
}
try { //CASE 6
is.read(b, 500, 10); //len+off > b.length
System.out.println( "CASE6: Failed - IndexOutOfBoundsException is not thrown" );
passed = false;
}
catch(IndexOutOfBoundsException ib) {
System.out.println( "CASE6: OK - IndexOutOfBoundsException thrown" );
}
if(!(
(a=is.read(new byte[183],0,183)) == 183 // Test no readings made
))
{ System.out.println("Failed: Unexpected readings performed: "+
(183-a)+ " bytes");
return false;
}
for(int j=0;j<b.length;j++)
if (!(
b[j] == (byte)(j+3) // Test bytes are untouched
)) { System.out.println( "Failed: bytes are touched: j="+j);
return false;
}
}
catch(Throwable e) { // Test no other exceptions thrown
System.out.println( "Unexpected "+e+" thrown" );
return false;
}
return passed;
}
public static void main (String argv[]) {
InflaterInputStream iis = null;
DeflaterOutputStream dos = null;
GZIPInputStream gis = null;
GZIPOutputStream gos = null;
ZipInputStream zis = null;
ZipOutputStream zo = null;
JarInputStream jis = null;
JarOutputStream jo = null;
ByteArrayOutputStream out=null;
Manifest manifest = null;
byte[] data = new byte[183];
for (int i=0; i<183; i++) data[i]=(byte)(i-3);
try {
// GZIPInputStream Testing
out=new ByteArrayOutputStream();
gos = new GZIPOutputStream(out); // open output
gos.write(data,0,183);
gos.close();
gis = new GZIPInputStream(new ByteArrayInputStream(out.toByteArray())); // create input
if ( readTest(gis) )
System.out.println("GZIPInputStream Test Passed OK !");
else System.out.println("GZIPInputStream Test Failed !");
// InflaterInputStream Testing
out=new ByteArrayOutputStream();
dos = new DeflaterOutputStream(out); // open output
dos.write(data,0,183);
dos.close();
iis = new InflaterInputStream(new ByteArrayInputStream(out.toByteArray())); // create input
if ( readTest(iis) )
System.out.println("InflaterInputStream Test Passed OK !");
else System.out.println("InflaterInputStream Test Failed !");
// ZipInputStream Testing
out=new ByteArrayOutputStream();
zo = new ZipOutputStream(out); // open output
zo.putNextEntry(new ZipEntry("entry1"));
zo.write(data);
zo.closeEntry();
zo.close();
zis = new ZipInputStream(new ByteArrayInputStream(out.toByteArray())); // create input
zis.getNextEntry();
if ( readTest(zis) )
System.out.println("ZipInputStream Test Passed OK !");
else System.out.println("ZipInputStream Test Failed !");
// JarInputStream Testing
out=new ByteArrayOutputStream();
manifest = new Manifest(new ByteArrayInputStream(manifestStream.getBytes("ISO8859_1")));
jo = new JarOutputStream(out); // open output
jo.putNextEntry(new JarEntry("entry1"));
jo.write(data);
jo.closeEntry();
jo.close();
jis = new JarInputStream(new ByteArrayInputStream(out.toByteArray())); // create input
jis.getNextJarEntry();
if ( readTest(jis) )
System.out.println("JarInputStream Test Passed OK !");
else System.out.println("JarInputStream Test Failed !");
} catch (Throwable e) {
close(gos);
System.out.println("Unexpected "+e);
}
return;
}
}
========= Sample run (JDK-1.2fcs-U) ==========
#>javac Test10.java
#>java Test10
CASE1: Failed - IndexOutOfBoundsException is not thrown
CASE2: Failed - IndexOutOfBoundsException is not thrown
CASE3: OK - IndexOutOfBoundsException thrown
CASE4: OK - IndexOutOfBoundsException thrown
CASE5: OK - IndexOutOfBoundsException thrown
CASE6: OK - IndexOutOfBoundsException thrown
GZIPInputStream Test Failed !
CASE1: Failed - IndexOutOfBoundsException is not thrown
CASE2: Failed - IndexOutOfBoundsException is not thrown
CASE3: OK - IndexOutOfBoundsException thrown
CASE4: Failed - IndexOutOfBoundsException is not thrown
CASE5: OK - IndexOutOfBoundsException thrown
CASE6: OK - IndexOutOfBoundsException thrown
InflaterInputStream Test Failed !
CASE1: Failed - IndexOutOfBoundsException is not thrown
CASE2: Failed - IndexOutOfBoundsException is not thrown
CASE3: OK - IndexOutOfBoundsException thrown
CASE4: OK - IndexOutOfBoundsException thrown
CASE5: OK - IndexOutOfBoundsException thrown
CASE6: OK - IndexOutOfBoundsException thrown
ZipInputStream Test Failed !
CASE1: Failed - IndexOutOfBoundsException is not thrown
CASE2: Failed - IndexOutOfBoundsException is not thrown
CASE3: OK - IndexOutOfBoundsException thrown
CASE4: OK - IndexOutOfBoundsException thrown
CASE5: OK - IndexOutOfBoundsException thrown
CASE6: OK - IndexOutOfBoundsException thrown
JarInputStream Test Failed !
======================================================================