Skip to content

Commit 53cf6ec

Browse files
committed
[TEXT-236] Inserting at end of a TextStringBuilder throws a
StringIndexOutOfBoundsException
1 parent 5ba7929 commit 53cf6ec

File tree

4 files changed

+60
-7
lines changed

4 files changed

+60
-7
lines changed

src/changes/changes.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ The <action> type attribute can be add,update,fix,remove.
4848
<release version="1.14.1" date="YYYY-MM-DD" description="This is a feature and maintenance release. Java 8 or later is required.">
4949
<!-- FIX -->
5050
<action type="fix" dev="ggregory" due-to="Gary Gregory">Fix exception message typo in XmlStringLookup.XmlStringLookup(Map, Path...).</action>
51+
<action type="fix" dev="ggregory" due-to="Sumit Bera, Alex Herbert, Gary Gregory" issue="TEXT-236">Inserting at end of a TextStringBuilder throws a StringIndexOutOfBoundsException.</action>
5152
<!-- ADD -->
5253
<action type="add" dev="ggregory" due-to="Piotr P. Karwasz, Gary Gregory">Add experimental CycloneDX VEX file #683.</action>
5354
<!-- UPDATE -->

src/conf/spotbugs-exclude-filter.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,4 +73,10 @@
7373
<Class name="org.apache.commons.text.similarity.LevenshteinDistance" />
7474
<Bug pattern="SING_SINGLETON_HAS_NONPRIVATE_CONSTRUCTOR" />
7575
</Match>
76+
<!-- RV_RETURN_VALUE_IGNORED_NO_SIDE_EFFECT false positive: Exceptions can be thrown -->
77+
<Match>
78+
<Class name="org.apache.commons.text.TextStringBuilder" />
79+
<Method name="insert" />
80+
<Bug pattern="RV_RETURN_VALUE_IGNORED_NO_SIDE_EFFECT" />
81+
</Match>
7682
</FindBugsFilter>

src/main/java/org/apache/commons/text/TextStringBuilder.java

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2190,7 +2190,7 @@ public int indexOf(final StringMatcher matcher, int startIndex) {
21902190
* @throws IndexOutOfBoundsException if the index is invalid
21912191
*/
21922192
public TextStringBuilder insert(final int index, final boolean value) {
2193-
validateIndex(index);
2193+
validateRange(index, size);
21942194
if (value) {
21952195
ensureCapacityInternal(size + TRUE_STRING_SIZE);
21962196
System.arraycopy(buffer, index, buffer, index + TRUE_STRING_SIZE, size - index);
@@ -2212,7 +2212,7 @@ public TextStringBuilder insert(final int index, final boolean value) {
22122212
* @throws IndexOutOfBoundsException if the index is invalid
22132213
*/
22142214
public TextStringBuilder insert(final int index, final char value) {
2215-
validateIndex(index);
2215+
validateRange(index, size);
22162216
ensureCapacityInternal(size + 1);
22172217
System.arraycopy(buffer, index, buffer, index + 1, size - index);
22182218
buffer[index] = value;
@@ -2229,7 +2229,7 @@ public TextStringBuilder insert(final int index, final char value) {
22292229
* @throws IndexOutOfBoundsException if the index is invalid
22302230
*/
22312231
public TextStringBuilder insert(final int index, final char[] chars) {
2232-
validateIndex(index);
2232+
validateRange(index, size);
22332233
if (chars == null) {
22342234
return insert(index, nullText);
22352235
}
@@ -2254,7 +2254,7 @@ public TextStringBuilder insert(final int index, final char[] chars) {
22542254
* @throws IndexOutOfBoundsException if any index is invalid
22552255
*/
22562256
public TextStringBuilder insert(final int index, final char[] chars, final int offset, final int length) {
2257-
validateIndex(index);
2257+
validateRange(index, size);
22582258
if (chars == null) {
22592259
return insert(index, nullText);
22602260
}
@@ -2346,7 +2346,7 @@ public TextStringBuilder insert(final int index, final Object obj) {
23462346
* @throws IndexOutOfBoundsException if the index is invalid
23472347
*/
23482348
public TextStringBuilder insert(final int index, String str) {
2349-
validateIndex(index);
2349+
validateRange(index, size);
23502350
if (str == null) {
23512351
str = nullText;
23522352
}
@@ -3208,10 +3208,10 @@ public TextStringBuilder trim() {
32083208
}
32093209

32103210
/**
3211-
* Validates that an index is in the range {@code 0 <= index <= size}.
3211+
* Validates that an index is in the range {@code 0 <= index < size}.
32123212
*
32133213
* @param index the index to test.
3214-
* @throws IndexOutOfBoundsException Thrown when the index is not the range {@code 0 <= index <= size}.
3214+
* @throws IndexOutOfBoundsException Thrown when the index is not the range {@code 0 <= index < size}.
32153215
*/
32163216
protected void validateIndex(final int index) {
32173217
if (index < 0 || index >= size) {

src/test/java/org/apache/commons/text/TextStringBuilderAppendInsertTest.java

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1133,6 +1133,52 @@ void testInsert() {
11331133
assertEquals("4.5barbaz", sb.toString());
11341134
}
11351135

1136+
@Test
1137+
void testInsertAtEnd() {
1138+
final TextStringBuilder sb = new TextStringBuilder();
1139+
assertEquals("", sb.toString());
1140+
sb.insert(0, "Hello");
1141+
assertEquals("Hello", sb.toString());
1142+
assertThrows(IndexOutOfBoundsException.class, () -> sb.insert(-1, "World"));
1143+
assertThrows(IndexOutOfBoundsException.class, () -> sb.insert(6, "World"));
1144+
sb.insert(5, true);
1145+
assertEquals("Hellotrue", sb.toString());
1146+
assertThrows(IndexOutOfBoundsException.class, () -> sb.insert(10, false));
1147+
assertThrows(IndexOutOfBoundsException.class, () -> sb.insert(-20, false));
1148+
sb.insert(9, 'A');
1149+
assertEquals("HellotrueA", sb.toString());
1150+
assertThrows(IndexOutOfBoundsException.class, () -> sb.insert(11, 'B'));
1151+
assertThrows(IndexOutOfBoundsException.class, () -> sb.insert(-2, 'B'));
1152+
sb.insert(10, new char[] { 'B', 'C' });
1153+
assertEquals("HellotrueABC", sb.toString());
1154+
assertThrows(IndexOutOfBoundsException.class, () -> sb.insert(13, new char[] { 'D', 'E' }));
1155+
assertThrows(IndexOutOfBoundsException.class, () -> sb.insert(-1, new char[] { 'D', 'E' }));
1156+
sb.insert(12, new char[] { 'D', 'E', 'F' }, 1, 1);
1157+
assertEquals("HellotrueABCE", sb.toString());
1158+
assertThrows(IndexOutOfBoundsException.class, () -> sb.insert(14, new char[] { 'G', 'H', 'I' }, 1, 2));
1159+
assertThrows(IndexOutOfBoundsException.class, () -> sb.insert(-1, new char[] { 'G', 'H', 'I' }, 1, 1));
1160+
sb.insert(13, 1.2d);
1161+
assertEquals("HellotrueABCE1.2", sb.toString());
1162+
assertThrows(IndexOutOfBoundsException.class, () -> sb.insert(17, 1.3d));
1163+
assertThrows(IndexOutOfBoundsException.class, () -> sb.insert(-1, 1.3d));
1164+
sb.insert(16, 1f);
1165+
assertEquals("HellotrueABCE1.21.0", sb.toString());
1166+
assertThrows(IndexOutOfBoundsException.class, () -> sb.insert(20, 1.3f));
1167+
assertThrows(IndexOutOfBoundsException.class, () -> sb.insert(-3, 1.3f));
1168+
sb.insert(19, 23);
1169+
assertEquals("HellotrueABCE1.21.023", sb.toString());
1170+
assertThrows(IndexOutOfBoundsException.class, () -> sb.insert(22, 20));
1171+
assertThrows(IndexOutOfBoundsException.class, () -> sb.insert(-5, -5));
1172+
sb.insert(21, 99L);
1173+
assertEquals("HellotrueABCE1.21.02399", sb.toString());
1174+
assertThrows(IndexOutOfBoundsException.class, () -> sb.insert(24, 22L));
1175+
assertThrows(IndexOutOfBoundsException.class, () -> sb.insert(-1, -1L));
1176+
sb.insert(23, FOO);
1177+
assertEquals("HellotrueABCE1.21.02399foo", sb.toString());
1178+
assertThrows(IndexOutOfBoundsException.class, () -> sb.insert(27, FOO));
1179+
assertThrows(IndexOutOfBoundsException.class, () -> sb.insert(-3, FOO));
1180+
}
1181+
11361182
@Test
11371183
void testInsertWithNullText() {
11381184
final TextStringBuilder sb = new TextStringBuilder();

0 commit comments

Comments
 (0)