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()); + } }