StringBuffer.java (getChars): Fix array index checks.
authorRalph Loader <rcl@ihug.co.nz>
Thu, 16 Oct 2003 21:35:42 +0000 (21:35 +0000)
committerRalph Loader <ralph@gcc.gnu.org>
Thu, 16 Oct 2003 21:35:42 +0000 (21:35 +0000)
* java/lang/StringBuffer.java (getChars): Fix array index checks.
(append, substring, insert): Likewise.
* testsuite/libjava.lang/StringBuffer_overflow.java: New file.
* testsuite/libjava.lang/StringBuffer_overflow.out: New file.

From-SVN: r72579

libjava/ChangeLog
libjava/java/lang/StringBuffer.java
libjava/testsuite/libjava.lang/StringBuffer_overflow.java [new file with mode: 0644]
libjava/testsuite/libjava.lang/StringBuffer_overflow.out [new file with mode: 0644]

index ef0511712b822790cf9a300a971b95cdfa2bbdcb..d751c102c114f03c39d270e9532a53265deded99 100644 (file)
@@ -1,3 +1,10 @@
+2003-10-17  Ralph Loader  <rcl@ihug.co.nz>
+
+       * java/lang/StringBuffer.java (getChars): Fix array index checks.
+       (append, substring, insert): Likewise.
+       * testsuite/libjava.lang/StringBuffer_overflow.java: New file.
+       * testsuite/libjava.lang/StringBuffer_overflow.out: New file.
+       
 2003-10-17  Ralph Loader  <rcl@ihug.co.nz>
 
        * java/lang/natString.cc (getChars):
index 0903b40cc5ffe0f4311593639de5ca2f35faafd0..92f961534a13bab006517d1c6859e0b692bcd167 100644 (file)
@@ -244,10 +244,9 @@ public final class StringBuffer implements Serializable, CharSequence
   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 final class StringBuffer implements Serializable, CharSequence
    */
   public synchronized StringBuffer append(char[] data, int offset, int count)
   {
+    if (offset < 0 || count < 0 || offset > data.length - 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 final class StringBuffer implements Serializable, CharSequence
   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 "";
@@ -589,7 +590,7 @@ public final class StringBuffer implements Serializable, CharSequence
                                           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);
diff --git a/libjava/testsuite/libjava.lang/StringBuffer_overflow.java b/libjava/testsuite/libjava.lang/StringBuffer_overflow.java
new file mode 100644 (file)
index 0000000..68e18da
--- /dev/null
@@ -0,0 +1,126 @@
+/* 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);
+      }
+  }
+
+  // Check that append still more or less works.
+  static void appendbasic()
+  {
+    StringBuffer s = new StringBuffer();
+
+    try
+      {
+       if (!new StringBuffer().append ("abcdefg".toCharArray())
+           .toString().equals ("abcdefg"))
+         {
+           Fail ("appendbasic", "append gives incorrect result");
+         }
+      }
+    catch (Throwable e)
+      {
+       Fail ("appendbasic", 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();
+    appendbasic();
+    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);
+  }
+}
diff --git a/libjava/testsuite/libjava.lang/StringBuffer_overflow.out b/libjava/testsuite/libjava.lang/StringBuffer_overflow.out
new file mode 100644 (file)
index 0000000..9766475
--- /dev/null
@@ -0,0 +1 @@
+ok