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

Java Spec for FileInputStream and RandomAccessFile read method not as designed

XMLWordPrintable

    • sparc
    • solaris_2.5.1

      Problem:
      *** We need to test for len < 0 then throw ArrayIndexOutOfBoundsException ***
      *** We need to test for off+len > datalen then throw ArrayIndexOutOfBoundsException ***

      The Java Specification Language: Reference 22.3.3
      public int read(byte[] b, int off, int len)
      throws IOException, NullPointerException,
      IndexOutOfBoundsException

      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.


      JAVA CODE for read calls native readBytes
      JAVA WORKSPACE TREE: /src/share/java/lang
      File: io.c

      Sections of code in question:
      *** java_io_FileInputStream_readBytes(Hjava_io_FileInputStream *this, HArrayOfByte *data, long off, long len)

      *** java_io_RandomAccessFile_readBytes(Hjava_io_RandomAccessFile *this, HArrayOfByte *data, long off, long len)

      Code snippet:
          dataptr = unhand(data)->body;
          datalen = obj_length(data);


      *** We need to test for below description in FileInputStream + RandomAccessFile native code for readBytes ***

      DESCRIPTION OF PROBLEM:

      *** We need to test for len < 0 then throw ArrayIndexOutOfBoundsException ***
      *** We need to test for off+len > datalen then throw ArrayIndexOutOfBoundsException ***


      *** Could use code: if ((off < 0) || (len < 0)|| ( off + len > datalen)||(off > datalen)) { ***

      *** Use above line instead of below line ***
          if ((off < 0) || (off > datalen)) { *** Does not check all cases for throwing exceptions
      SignalError(0, JAVAPKG "ArrayIndexOutOfBoundsException", 0);
      return -1;
          }

      ********************************************************
      *** This should be covered above and throw exception ***

          if (off + len > datalen) {
      len = datalen - off;
          }
      ********************************************************

      ********************************************************
      *** Change the len <= 0 to len = 0 the return zero ***
          if (len <= 0) {
      return 0;
          }
      ********************************************************
          n = sysReadFD(fdptr, dataptr + off, len);
          if (n == -1) {
      SignalError(0, IO_EXCEPTION, "read error");
          }

          /* AVH: this is bogus but it stops the pointer from being gc'd */
          KEEP_POINTER_ALIVE(dataptr);
          return (n == 0) ? -1 : n;

      *******************************************************************************************

      How to reproduce bug:
      Use below test to test against errors:
      change (off) and (len) values described below.

      off=0 len=5 buf.size=5 This will test if we can read array size that matches off+len
      off=1 len=5 buf.size=5 This will test if off+len is greater than buf.size then throw exception
      off=-1 len=5 buf.size=5 This will test if off is negative then throw exception
      off=1 len=-5 buf.size=5 This will test if len is negative then throw exception
      off=6 len=1 buf.size=5 This will test if off is greater than buf.size then throw exception

      Test Code:

      import java.io.*;

      public class readbytes_test {

          public static void main(String argv[]) {
            try {
      byte buf[] = new byte[5];
      int off = 0;
      int len = 5;
      // Tests that need to be run
      // off=0 len=5 buf.size=5 This will test if we can read array size that matches off+len
      // off=1 len=5 buf.size=5 This will test if off+len is greater than buf.size then throw exception
      // off=-1 len=5 buf.size=5 This will test if off is negative then throw exception
      // off=1 len=-5 buf.size=5 This will test if len is negative then throw exception
      // off=6 len=1 buf.size=5 This will test if off is greater than buf.size then throw exception


      // Test for FileInputStream (read) Method which calls native readBytes

      FileInputStream f = new FileInputStream("./test.txt");
      System.out.println("Array.length = "+buf.length);
      System.out.println("Bytes Read: " + f.read(buf, off, len));

      // Loops through array and prints out buffer values

      for (int i = 0; i < buf.length; i++){
      System.out.println("buffer["+i+"] value = " + buf[i]);
      }

      // Test for RandomAccessFile (read) Method which calls native readBytes

      RandomAccessFile raf = new RandomAccessFile("./test.txt", "r");
      System.out.println("Array.length = "+buf.length);
      System.out.println("Bytes Read: " + f.read(buf, off, len));

      // Loops through array and prints out buffer values

      for (int i = 0; i < buf.length; i++){
      System.out.println("buf["+i+"] = " + buf[i]);
      }
            }
            catch (Exception x) {
      x.printStackTrace();
            }
          }
      }



            dviswanasunw Deepa Viswanathan (Inactive)
            collins Gary Collins (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: