Fix [Issue-24] for 1.9

diff --git a/release-notes/VERSION b/release-notes/VERSION
index 6c06eed..9051882 100644
--- a/release-notes/VERSION
+++ b/release-notes/VERSION
@@ -11,6 +11,7 @@
   * [Issue-21]: Improve handling of String hash code collisions for
    symbol tables; exception for degenerate cases (attacks), improvements
    for calculation otherwise
+  * [Issue-24]: ArrayIndexOutOfBoundsException with TextBuffer.append()
   * [JACKSON-853]: JsonStringEncoder.quoteAsString() problem with buffer boundary
 
 ------------------------------------------------------------------------
diff --git a/src/java/org/codehaus/jackson/util/TextBuffer.java b/src/java/org/codehaus/jackson/util/TextBuffer.java
index 3fdbc78..8f1eff1 100644
--- a/src/java/org/codehaus/jackson/util/TextBuffer.java
+++ b/src/java/org/codehaus/jackson/util/TextBuffer.java
@@ -457,19 +457,26 @@
         if (max >= len) {
             System.arraycopy(c, start, curr, _currentSize, len);
             _currentSize += len;
-        } else {
-            // No room for all, need to copy part(s):
-            if (max > 0) {
-                System.arraycopy(c, start, curr, _currentSize, max);
-                start += max;
-                len -= max;
-            }
-            // And then allocate new segment; we are guaranteed to now
-            // have enough room in segment.
-            expand(len); // note: curr != _currentSegment after this
-            System.arraycopy(c, start, _currentSegment, 0, len);
-            _currentSize = len;
+	    return;
+	}
+        // No room for all, need to copy part(s):
+        if (max > 0) {
+            System.arraycopy(c, start, curr, _currentSize, max);
+            start += max;
+            len -= max;
         }
+        /* And then allocate new segment; we are guaranteed to now
+         * have enough room in segment.
+         */
+        // Except, as per [Issue-24], not for HUGE appends... so:
+        do {
+            expand(len);
+            int amount = Math.min(_currentSegment.length, len);
+            System.arraycopy(c, start, _currentSegment, 0, amount);
+            _currentSize += amount;
+            start += amount;
+            len -= amount;
+        } while (len > 0);
     }
 
     public void append(String str, int offset, int len)
@@ -487,20 +494,26 @@
         if (max >= len) {
             str.getChars(offset, offset+len, curr, _currentSize);
             _currentSize += len;
-        } else {
-            // No room for all, need to copy part(s):
-            if (max > 0) {
-                str.getChars(offset, offset+max, curr, _currentSize);
-                len -= max;
-                offset += max;
-            }
-            /* And then allocate new segment; we are guaranteed to now
-             * have enough room in segment.
-             */
-            expand(len);
-            str.getChars(offset, offset+len, _currentSegment, 0);
-            _currentSize = len;
+	    return;
+	}
+        // No room for all, need to copy part(s):
+        if (max > 0) {
+            str.getChars(offset, offset+max, curr, _currentSize);
+            len -= max;
+            offset += max;
         }
+        /* And then allocate new segment; we are guaranteed to now
+         * have enough room in segment.
+         */
+        // Except, as per [Issue-24], not for HUGE appends... so:
+        do {
+            expand(len);
+            int amount = Math.min(_currentSegment.length, len);
+            str.getChars(offset, offset+amount, _currentSegment, 0);
+            _currentSize += amount;
+            offset += amount;
+            len -= amount;
+        } while (len > 0);
     }
 
     /*
diff --git a/src/test/org/codehaus/jackson/util/TestTextBuffer.java b/src/test/org/codehaus/jackson/util/TestTextBuffer.java
index 6dda7f6..2a0b783 100644
--- a/src/test/org/codehaus/jackson/util/TestTextBuffer.java
+++ b/src/test/org/codehaus/jackson/util/TestTextBuffer.java
@@ -32,4 +32,32 @@
         tb.resetWithShared(new char[] { 'a' }, 0, 1);
         assertEquals(1, tb.toString().length());
     }
+
+    // [Issue-24]
+    public void testLongAppend()
+    {
+        final int len = TextBuffer.MAX_SEGMENT_LEN * 3 / 2;
+        StringBuilder sb = new StringBuilder(len);
+        for (int i = 0; i < len; ++i) {
+            sb.append('x');
+        }
+        final String STR = sb.toString();
+        final String EXP = "a" + STR + "c";
+
+        // ok: first test with String:
+        TextBuffer tb = new TextBuffer(new BufferRecycler());
+        tb.append('a');
+        tb.append(STR, 0, len);
+        tb.append('c');
+        assertEquals(len+2, tb.size());
+        assertEquals(EXP, tb.contentsAsString());
+
+        // then char[]
+        tb = new TextBuffer(new BufferRecycler());
+        tb.append('a');
+        tb.append(STR.toCharArray(), 0, len);
+        tb.append('c');
+        assertEquals(len+2, tb.size());
+        assertEquals(EXP, tb.contentsAsString());
+    }
 }