This is the mail archive of the java-patches@gcc.gnu.org mailing list for the Java project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Patch] StringBuffer.java index checking.


This fixes 4 cases of index checking in StringBuffer, with test cases.

Passes make check in libjava.

In each case, the comments indicate that StringIndexOutOfBoundsException
should be thrown.  Without the fixes, ArrayIndexOutOfBoundsException can
be thrown.

Again, there are more cases where integer overflow might happen, but you
probably need large amounts of memory to trigger them.

2003-09-24  Ralph Loader  <suckfish@ihug.co.nz>

	* java/lang/StringBuffer.java (getChars): Fix array index checks.
	(append, substring, insert): Likewide.
	* testsuite/libjava.lang/StringBuffer_overflow.java: New file.
	* testsuite/libjava.lang/StringBuffer_overflow.out: New file.

Ralph.

Index: libjava/java/lang/StringBuffer.java
===================================================================
RCS file: /cvsroot/gcc/gcc/libjava/java/lang/StringBuffer.java,v
retrieving revision 1.16
diff -u -u -r1.16 StringBuffer.java
--- libjava/java/lang/StringBuffer.java	22 Sep 2003 08:17:48 -0000	1.16
+++ libjava/java/lang/StringBuffer.java	23 Sep 2003 20:46:46 -0000
@@ -244,10 +244,9 @@
   public synchronized void getChars(int srcOffset, int srcEnd,
                                     char[] dst, int dstOffset)
   {
-    int todo = srcEnd - srcOffset;
-    if (srcOffset < 0 || srcEnd > count || todo < 0)
+    if (srcOffset < 0 || srcEnd > count || srcEnd < srcOffset)
       throw new StringIndexOutOfBoundsException();
-    System.arraycopy(value, srcOffset, dst, dstOffset, todo);
+    System.arraycopy(value, srcOffset, dst, dstOffset, srcEnd - srcOffset);
   }
 
   /**
@@ -355,6 +354,8 @@
    */
   public synchronized StringBuffer append(char[] data, int offset, int count)
   {
+    if (offset < 0 || count < 0 || offset > this.count - count)
+      throw new StringIndexOutOfBoundsException();
     ensureCapacity_unsynchronized(this.count + count);
     System.arraycopy(data, offset, value, this.count, count);
     this.count += count;
@@ -560,7 +561,7 @@
   public synchronized String substring(int beginIndex, int endIndex)
   {
     int len = endIndex - beginIndex;
-    if (beginIndex < 0 || endIndex > count || len < 0)
+    if (beginIndex < 0 || endIndex > count || endIndex < beginIndex)
       throw new StringIndexOutOfBoundsException();
     if (len == 0)
       return "";
@@ -588,7 +589,7 @@
                                           char[] str, int str_offset, int len)
   {
     if (offset < 0 || offset > count || len < 0
-        || str_offset < 0 || str_offset + len > str.length)
+        || str_offset < 0 || str_offset > str.length - len)
       throw new StringIndexOutOfBoundsException();
     ensureCapacity_unsynchronized(count + len);
     System.arraycopy(value, offset, value, offset + len, count - offset);
--- /dev/null	2003-09-16 01:40:47.000000000 +1200
+++ libjava/testsuite/libjava.lang/StringBuffer_overflow.java	2003-09-23 18:54:44.000000000 +1200
@@ -0,0 +1,106 @@
+/* This tests some corner cases of arithmetic in StringBuffer.  */
+
+/* These tests can all be run on a 32 bit machine with modest amounts
+ * of memory.  */
+
+/* The symptom of the problem is that ArrayIndexOutOfBoundsException
+ * gets thrown, while the documentation says that
+ * StringIndexOutOfBoundsException should be thrown.  */
+
+class StringBuffer_overflow
+{
+  /* Test correct exception on getChars.  */
+  static void getChars()
+  {
+    StringBuffer b = new StringBuffer ("x");
+    char[] s = new char [1];
+    try
+      {
+	// The substring we are attempting to obtain is invalid,
+	// so we should get a StringIndexOutOfBoundsException.
+	b.getChars (1, -1 << 31, s, 0);
+	Fail ("getChars", "no exception");
+      }
+    catch (Throwable e)
+      {
+	ExpectStringIndex ("getChars()", e);
+      }
+  }
+
+  /* Test correct exception on append with bogus count. */
+  static void append()
+  {
+    StringBuffer s = new StringBuffer("a");
+    try
+      {
+	s.append ("".toCharArray(), 1, (1<<31)-1);
+	Fail ("append", "no exception");
+      }
+    catch (Throwable e)
+      {
+	ExpectStringIndex ("append", e);
+      }
+  }
+
+  /* Test correct expception on substring with bogus indexes.  */
+  static void substring()
+  {
+    StringBuffer s = new StringBuffer ("abc");
+    try
+      {
+	// end - begin == -2 - ((1<<31)-1) == (1<<31) - 1 > 0.  */
+	s.substring ((1<<31)-1, -2);
+	Fail ("substring", "no exception");
+      }
+    catch (Throwable e)
+      {
+	ExpectStringIndex ("substring", e);
+      }
+  }
+
+  static void insert()
+  {
+    StringBuffer s = new StringBuffer ("");
+    try
+      {
+	s.insert (0, "abcd".toCharArray(), (1<<31)-1, 1);
+	Fail ("insert", "no exception");
+      }
+    catch (Throwable e)
+      {
+	ExpectStringIndex ("insert", e);
+      }
+  }
+
+
+  public static void main (String[] unused)
+  {
+    getChars();
+    append();
+    substring();
+    insert();
+
+    if (tests_failed == 0)
+      {
+	System.out.println ("ok");
+      }
+  }
+
+  static int tests_failed = 0;
+
+  static void ExpectStringIndex (String name, Throwable exception)
+  {
+    if (! (exception instanceof StringIndexOutOfBoundsException))
+      {
+	Fail (name, exception);
+      }
+  }
+  static void Fail (String name, Object why)
+  {
+    ++tests_failed;
+
+    System.err.print (name);
+    System.err.print ('\t');
+    System.err.println (why);
+  }
+}
--- /dev/null	2003-09-16 01:40:47.000000000 +1200
+++ libjava/testsuite/libjava.lang/StringBuffer_overflow.out	2003-09-23 18:52:32.000000000 +1200
@@ -0,0 +1 @@
+ok

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]