Repository: netty/netty
Issue: The public int lastIndexOf(CharSequence string) method of the AsciiString class always returns -1
Labels: defect

public int lastIndexOf(CharSequence string) {
        // Use count instead of count - 1 so lastIndexOf("") answers count
        return lastIndexOf(string, length());
    }

@Test
    public void test004(){
        byte[] bytes = new byte[]{1,2,3,4,5,6,7,8,9,10};
        AsciiString ascii = new AsciiString(bytes, 0, 10, false);
        int b = ascii.lastIndexOf("6");
        System.out.println(b);

    }

the result is -1.

Issue comments:
- Which version do you use?
- -1 means no substring found.
- 6 in array `bytes` of your method `test004()` is a byte which will be interpreted `\u0006` in AsciiString, while "6" is a string  whose ascii value is `\u0036`. Combination of these two fact means the result is -1 even if the method `lastIndexOf` is bug free.
- `byte[] bytes =  new byte['1', '2', '3', '4', '5', '6', '7', '8', '9'] ` may be what you want.


- i  use netty-4.1.34 version.

- Based on your comments, I added a test case：
@Test
    public void test005(){
        AsciiString ascii = new AsciiString("12345678910");
        int b = ascii.lastIndexOf("6");
        System.out.println(b);

    }
   But the result is still -1, this is not what I expected.In my opinion, this should return 5.

   I looked at the source code,

   public int lastIndexOf(CharSequence string) {
   // Use count instead of count - 1 so lastIndexOf("") answers count
   return lastIndexOf(string, length());
   }

   lastIndexOf(string, length()) should be modified to lastIndexOf(string, 0) ?

@xiaoheng1 You're right. I also checked the source code. This should be an issue, I will do PR later.
OK,  Thanks!
Thanks @xiaoheng1, have opened #9103 to address this.
OK, Thanks!

Pull request review comments:

Patch that resolved the issue:
diff --git a/common/src/main/java/io/netty/util/AsciiString.java b/common/src/main/java/io/netty/util/AsciiString.java
index 302b36e89bc..248ae88b214 100644
--- a/common/src/main/java/io/netty/util/AsciiString.java
+++ b/common/src/main/java/io/netty/util/AsciiString.java
@@ -742,7 +742,7 @@ public int indexOf(char ch, int start) {
      */
     public int lastIndexOf(CharSequence string) {
         // Use count instead of count - 1 so lastIndexOf("") answers count
-        return lastIndexOf(string, length());
+        return lastIndexOf(string, length);
     }
 
     /**
@@ -757,23 +757,20 @@ public int lastIndexOf(CharSequence string) {
      */
     public int lastIndexOf(CharSequence subString, int start) {
         final int subCount = subString.length();
+        start = Math.min(start, length - subCount);
         if (start < 0) {
-            start = 0;
-        }
-        if (subCount <= 0) {
-            return start < length ? start : length;
-        }
-        if (subCount > length - start) {
             return INDEX_NOT_FOUND;
         }
+        if (subCount == 0) {
+            return start;
+        }
 
         final char firstChar = subString.charAt(0);
         if (firstChar > MAX_CHAR_VALUE) {
             return INDEX_NOT_FOUND;
         }
         final byte firstCharAsByte = c2b0(firstChar);
-        final int end = offset + start;
-        for (int i = offset + length - subCount; i >= end; --i) {
+        for (int i = offset + start; i >= 0; --i) {
             if (value[i] == firstCharAsByte) {
                 int o1 = i, o2 = 0;
                 while (++o2 < subCount && b2c(value[++o1]) == subString.charAt(o2)) {


Test patch:
diff --git a/common/src/test/java/io/netty/util/AsciiStringCharacterTest.java b/common/src/test/java/io/netty/util/AsciiStringCharacterTest.java
index c2a835df660..deff4267d65 100644
--- a/common/src/test/java/io/netty/util/AsciiStringCharacterTest.java
+++ b/common/src/test/java/io/netty/util/AsciiStringCharacterTest.java
@@ -356,15 +356,15 @@ public void testStaticIndexOfChar() {
     @Test
     public void testLastIndexOfCharSequence() {
         assertEquals(0, new AsciiString("abcd").lastIndexOf("abcd", 0));
-        assertEquals(0, new AsciiString("abcd").lastIndexOf("abc", 0));
-        assertEquals(1, new AsciiString("abcd").lastIndexOf("bcd", 0));
-        assertEquals(1, new AsciiString("abcd").lastIndexOf("bc", 0));
-        assertEquals(5, new AsciiString("abcdabcd").lastIndexOf("bcd", 0));
-        assertEquals(0, new AsciiString("abcd", 1, 2).lastIndexOf("bc", 0));
-        assertEquals(0, new AsciiString("abcd", 1, 3).lastIndexOf("bcd", 0));
-        assertEquals(1, new AsciiString("abcdabcd", 4, 4).lastIndexOf("bcd", 0));
+        assertEquals(0, new AsciiString("abcd").lastIndexOf("abc", 4));
+        assertEquals(1, new AsciiString("abcd").lastIndexOf("bcd", 4));
+        assertEquals(1, new AsciiString("abcd").lastIndexOf("bc", 4));
+        assertEquals(5, new AsciiString("abcdabcd").lastIndexOf("bcd", 10));
+        assertEquals(0, new AsciiString("abcd", 1, 2).lastIndexOf("bc", 2));
+        assertEquals(0, new AsciiString("abcd", 1, 3).lastIndexOf("bcd", 3));
+        assertEquals(1, new AsciiString("abcdabcd", 4, 4).lastIndexOf("bcd", 4));
         assertEquals(3, new AsciiString("012345").lastIndexOf("345", 3));
-        assertEquals(3, new AsciiString("012345").lastIndexOf("345", 0));
+        assertEquals(3, new AsciiString("012345").lastIndexOf("345", 6));
 
         // Test with empty string
         assertEquals(0, new AsciiString("abcd").lastIndexOf("", 0));
@@ -376,7 +376,7 @@ public void testLastIndexOfCharSequence() {
         assertEquals(-1, new AsciiString("abcdbc").lastIndexOf("bce", 0));
         assertEquals(-1, new AsciiString("abcd", 1, 3).lastIndexOf("abc", 0));
         assertEquals(-1, new AsciiString("abcd", 1, 2).lastIndexOf("bd", 0));
-        assertEquals(-1, new AsciiString("012345").lastIndexOf("345", 4));
+        assertEquals(-1, new AsciiString("012345").lastIndexOf("345", 2));
         assertEquals(-1, new AsciiString("012345").lastIndexOf("abc", 3));
         assertEquals(-1, new AsciiString("012345").lastIndexOf("abc", 0));
         assertEquals(-1, new AsciiString("012345").lastIndexOf("abcdefghi", 0));