This is an automated email from the ASF dual-hosted git repository.
garydgregory pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-lang.git
The following commit(s) were added to refs/heads/master by this push:
new 35d652e9e Fix Strings.CI.indexOf returning out-of-range index for
empty search (#1737)
35d652e9e is described below
commit 35d652e9e26461ddbeb19aa32bc6acd012ccc641
Author: alhuda <[email protected]>
AuthorDate: Tue Jun 30 18:52:40 2026 +0530
Fix Strings.CI.indexOf returning out-of-range index for empty search (#1737)
* fix Strings.CI.indexOf returning out-of-range index for empty search
* Refactor test, add assertions.
---------
Co-authored-by: Gary Gregory <[email protected]>
---
src/main/java/org/apache/commons/lang3/Strings.java | 2 +-
.../java/org/apache/commons/lang3/StringsTest.java | 20 ++++++++++++++++++++
2 files changed, 21 insertions(+), 1 deletion(-)
diff --git a/src/main/java/org/apache/commons/lang3/Strings.java
b/src/main/java/org/apache/commons/lang3/Strings.java
index 213f4d1af..32ca691c5 100644
--- a/src/main/java/org/apache/commons/lang3/Strings.java
+++ b/src/main/java/org/apache/commons/lang3/Strings.java
@@ -152,7 +152,7 @@ public int indexOf(final CharSequence str, final
CharSequence searchStr, int sta
startPos = 0;
}
final int endLimit = str.length() - searchStr.length() + 1;
- if (startPos > endLimit) {
+ if (startPos >= endLimit) {
return INDEX_NOT_FOUND;
}
if (searchStr.length() == 0) {
diff --git a/src/test/java/org/apache/commons/lang3/StringsTest.java
b/src/test/java/org/apache/commons/lang3/StringsTest.java
index db39ef8ee..45227bfd1 100644
--- a/src/test/java/org/apache/commons/lang3/StringsTest.java
+++ b/src/test/java/org/apache/commons/lang3/StringsTest.java
@@ -59,6 +59,26 @@ void testCaseInsensitiveConstant() {
assertFalse(Strings.CI.isCaseSensitive());
}
+ /**
+ * For an empty search the case-insensitive {@code indexOf} returned
{@code startPos} unchanged once it reached
+ * {@code str.length() + 1}, so a start position one past the end yielded
an index beyond the string instead of
+ * {@code -1}.
+ */
+ @Test
+ void testCaseInsensitiveIndexOfEmptyOutOfRange() {
+ // repro: returned 4 (past the end of a length-3 string) before the fix
+ final String emptySearch = StringUtils.EMPTY;
+ assertEquals(-1, Strings.CI.indexOf("abc", emptySearch, 4));
+ // documented out-of-range example, also -1
+ assertEquals(-1, Strings.CI.indexOf("abc", emptySearch, 9));
+ // the end position is still a valid empty match
+ assertEquals(3, Strings.CI.indexOf("abc", emptySearch, 3));
+ assertEquals(2, Strings.CI.indexOf("aabaabaa", emptySearch, 2));
+ assertEquals(0, Strings.CI.indexOf(emptySearch, emptySearch, 0));
+ assertEquals(0, Strings.CI.indexOf(emptySearch, emptySearch, -1));
+ assertEquals(0, Strings.CI.indexOf("a", emptySearch, -1));
+ }
+
/**
* {@code U+0130} lower-cases to the two-char sequence {@code "i̇"}
outside Turkish locales, so pre-lower-casing the
* search argument made the case-insensitive replace look for a two-char
needle that no longer matches the single source