You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by gg...@apache.org on 2025/08/30 17:35:01 UTC
(commons-text) 02/02: [TEXT-236] Inserting at end of a TextStringBuilder throws a StringIndexOutOfBoundsException
This is an automated email from the ASF dual-hosted git repository.
ggregory pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-text.git
commit 53cf6ece273622821c5aa13444800ba94a69be55
Author: Gary D. Gregory <ga...@gmail.com>
AuthorDate: Sat Aug 30 13:34:54 2025 -0400
[TEXT-236] Inserting at end of a TextStringBuilder throws a
StringIndexOutOfBoundsException
---
src/changes/changes.xml | 1 +
src/conf/spotbugs-exclude-filter.xml | 6 +++
.../org/apache/commons/text/TextStringBuilder.java | 14 +++----
.../text/TextStringBuilderAppendInsertTest.java | 46 ++++++++++++++++++++++
4 files changed, 60 insertions(+), 7 deletions(-)
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index df97b651..362314fa 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -48,6 +48,7 @@ The <action> type attribute can be add,update,fix,remove.
<release version="1.14.1" date="YYYY-MM-DD" description="This is a feature and maintenance release. Java 8 or later is required.">
<!-- FIX -->
<action type="fix" dev="ggregory" due-to="Gary Gregory">Fix exception message typo in XmlStringLookup.XmlStringLookup(Map, Path...).</action>
+ <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>
<!-- ADD -->
<action type="add" dev="ggregory" due-to="Piotr P. Karwasz, Gary Gregory">Add experimental CycloneDX VEX file #683.</action>
<!-- UPDATE -->
diff --git a/src/conf/spotbugs-exclude-filter.xml b/src/conf/spotbugs-exclude-filter.xml
index 546e6193..c2b01f6b 100644
--- a/src/conf/spotbugs-exclude-filter.xml
+++ b/src/conf/spotbugs-exclude-filter.xml
@@ -73,4 +73,10 @@
<Class name="org.apache.commons.text.similarity.LevenshteinDistance" />
<Bug pattern="SING_SINGLETON_HAS_NONPRIVATE_CONSTRUCTOR" />
</Match>
+ <!-- RV_RETURN_VALUE_IGNORED_NO_SIDE_EFFECT false positive: Exceptions can be thrown -->
+ <Match>
+ <Class name="org.apache.commons.text.TextStringBuilder" />
+ <Method name="insert" />
+ <Bug pattern="RV_RETURN_VALUE_IGNORED_NO_SIDE_EFFECT" />
+ </Match>
</FindBugsFilter>
diff --git a/src/main/java/org/apache/commons/text/TextStringBuilder.java b/src/main/java/org/apache/commons/text/TextStringBuilder.java
index 1f194220..503bb056 100644
--- a/src/main/java/org/apache/commons/text/TextStringBuilder.java
+++ b/src/main/java/org/apache/commons/text/TextStringBuilder.java
@@ -2190,7 +2190,7 @@ public class TextStringBuilder implements CharSequence, Appendable, Serializable
* @throws IndexOutOfBoundsException if the index is invalid
*/
public TextStringBuilder insert(final int index, final boolean value) {
- validateIndex(index);
+ validateRange(index, size);
if (value) {
ensureCapacityInternal(size + TRUE_STRING_SIZE);
System.arraycopy(buffer, index, buffer, index + TRUE_STRING_SIZE, size - index);
@@ -2212,7 +2212,7 @@ public class TextStringBuilder implements CharSequence, Appendable, Serializable
* @throws IndexOutOfBoundsException if the index is invalid
*/
public TextStringBuilder insert(final int index, final char value) {
- validateIndex(index);
+ validateRange(index, size);
ensureCapacityInternal(size + 1);
System.arraycopy(buffer, index, buffer, index + 1, size - index);
buffer[index] = value;
@@ -2229,7 +2229,7 @@ public class TextStringBuilder implements CharSequence, Appendable, Serializable
* @throws IndexOutOfBoundsException if the index is invalid
*/
public TextStringBuilder insert(final int index, final char[] chars) {
- validateIndex(index);
+ validateRange(index, size);
if (chars == null) {
return insert(index, nullText);
}
@@ -2254,7 +2254,7 @@ public class TextStringBuilder implements CharSequence, Appendable, Serializable
* @throws IndexOutOfBoundsException if any index is invalid
*/
public TextStringBuilder insert(final int index, final char[] chars, final int offset, final int length) {
- validateIndex(index);
+ validateRange(index, size);
if (chars == null) {
return insert(index, nullText);
}
@@ -2346,7 +2346,7 @@ public class TextStringBuilder implements CharSequence, Appendable, Serializable
* @throws IndexOutOfBoundsException if the index is invalid
*/
public TextStringBuilder insert(final int index, String str) {
- validateIndex(index);
+ validateRange(index, size);
if (str == null) {
str = nullText;
}
@@ -3208,10 +3208,10 @@ public class TextStringBuilder implements CharSequence, Appendable, Serializable
}
/**
- * Validates that an index is in the range {@code 0 <= index <= size}.
+ * Validates that an index is in the range {@code 0 <= index < size}.
*
* @param index the index to test.
- * @throws IndexOutOfBoundsException Thrown when the index is not the range {@code 0 <= index <= size}.
+ * @throws IndexOutOfBoundsException Thrown when the index is not the range {@code 0 <= index < size}.
*/
protected void validateIndex(final int index) {
if (index < 0 || index >= size) {
diff --git a/src/test/java/org/apache/commons/text/TextStringBuilderAppendInsertTest.java b/src/test/java/org/apache/commons/text/TextStringBuilderAppendInsertTest.java
index 6d7a33c1..51e431f5 100644
--- a/src/test/java/org/apache/commons/text/TextStringBuilderAppendInsertTest.java
+++ b/src/test/java/org/apache/commons/text/TextStringBuilderAppendInsertTest.java
@@ -1133,6 +1133,52 @@ class TextStringBuilderAppendInsertTest {
assertEquals("4.5barbaz", sb.toString());
}
+ @Test
+ void testInsertAtEnd() {
+ final TextStringBuilder sb = new TextStringBuilder();
+ assertEquals("", sb.toString());
+ sb.insert(0, "Hello");
+ assertEquals("Hello", sb.toString());
+ assertThrows(IndexOutOfBoundsException.class, () -> sb.insert(-1, "World"));
+ assertThrows(IndexOutOfBoundsException.class, () -> sb.insert(6, "World"));
+ sb.insert(5, true);
+ assertEquals("Hellotrue", sb.toString());
+ assertThrows(IndexOutOfBoundsException.class, () -> sb.insert(10, false));
+ assertThrows(IndexOutOfBoundsException.class, () -> sb.insert(-20, false));
+ sb.insert(9, 'A');
+ assertEquals("HellotrueA", sb.toString());
+ assertThrows(IndexOutOfBoundsException.class, () -> sb.insert(11, 'B'));
+ assertThrows(IndexOutOfBoundsException.class, () -> sb.insert(-2, 'B'));
+ sb.insert(10, new char[] { 'B', 'C' });
+ assertEquals("HellotrueABC", sb.toString());
+ assertThrows(IndexOutOfBoundsException.class, () -> sb.insert(13, new char[] { 'D', 'E' }));
+ assertThrows(IndexOutOfBoundsException.class, () -> sb.insert(-1, new char[] { 'D', 'E' }));
+ sb.insert(12, new char[] { 'D', 'E', 'F' }, 1, 1);
+ assertEquals("HellotrueABCE", sb.toString());
+ assertThrows(IndexOutOfBoundsException.class, () -> sb.insert(14, new char[] { 'G', 'H', 'I' }, 1, 2));
+ assertThrows(IndexOutOfBoundsException.class, () -> sb.insert(-1, new char[] { 'G', 'H', 'I' }, 1, 1));
+ sb.insert(13, 1.2d);
+ assertEquals("HellotrueABCE1.2", sb.toString());
+ assertThrows(IndexOutOfBoundsException.class, () -> sb.insert(17, 1.3d));
+ assertThrows(IndexOutOfBoundsException.class, () -> sb.insert(-1, 1.3d));
+ sb.insert(16, 1f);
+ assertEquals("HellotrueABCE1.21.0", sb.toString());
+ assertThrows(IndexOutOfBoundsException.class, () -> sb.insert(20, 1.3f));
+ assertThrows(IndexOutOfBoundsException.class, () -> sb.insert(-3, 1.3f));
+ sb.insert(19, 23);
+ assertEquals("HellotrueABCE1.21.023", sb.toString());
+ assertThrows(IndexOutOfBoundsException.class, () -> sb.insert(22, 20));
+ assertThrows(IndexOutOfBoundsException.class, () -> sb.insert(-5, -5));
+ sb.insert(21, 99L);
+ assertEquals("HellotrueABCE1.21.02399", sb.toString());
+ assertThrows(IndexOutOfBoundsException.class, () -> sb.insert(24, 22L));
+ assertThrows(IndexOutOfBoundsException.class, () -> sb.insert(-1, -1L));
+ sb.insert(23, FOO);
+ assertEquals("HellotrueABCE1.21.02399foo", sb.toString());
+ assertThrows(IndexOutOfBoundsException.class, () -> sb.insert(27, FOO));
+ assertThrows(IndexOutOfBoundsException.class, () -> sb.insert(-3, FOO));
+ }
+
@Test
void testInsertWithNullText() {
final TextStringBuilder sb = new TextStringBuilder();