diff --git a/kotlin-native/runtime/src/main/cpp/KString.cpp b/kotlin-native/runtime/src/main/cpp/KString.cpp index 934812d2a3f..92f82dd0345 100644 --- a/kotlin-native/runtime/src/main/cpp/KString.cpp +++ b/kotlin-native/runtime/src/main/cpp/KString.cpp @@ -398,14 +398,20 @@ KInt Kotlin_String_indexOfString(KString thiz, KString other, KInt fromIndex) { if (other->count_ == 0) { return fromIndex; } - const KChar* thizRaw = CharArrayAddressOfElementAt(thiz, fromIndex); + const KChar* thizRaw = CharArrayAddressOfElementAt(thiz, 0); const KChar* otherRaw = CharArrayAddressOfElementAt(other, 0); - void* result = konan::memmem(thizRaw, (thiz->count_ - fromIndex) * sizeof(KChar), - otherRaw, other->count_ * sizeof(KChar)); - if (result == nullptr) return -1; - - return (reinterpret_cast(result) - reinterpret_cast( - CharArrayAddressOfElementAt(thiz, 0))) / sizeof(KChar); + const auto otherSize = other->count_ * sizeof(KChar); + while (true) { + void* result = konan::memmem(thizRaw + fromIndex, (thiz->count_ - fromIndex) * sizeof(KChar), + otherRaw, otherSize); + if (result == nullptr) return -1; + auto byteIndex = reinterpret_cast(result) - reinterpret_cast(thizRaw); + if (byteIndex % sizeof(KChar) == 0) { + return byteIndex / sizeof(KChar); + } else { + fromIndex = byteIndex / sizeof(KChar) + 1; + } + } } KInt Kotlin_String_lastIndexOfString(KString thiz, KString other, KInt fromIndex) { diff --git a/libraries/stdlib/test/text/StringTest.kt b/libraries/stdlib/test/text/StringTest.kt index 7d4e4910548..72e5e55c3f3 100644 --- a/libraries/stdlib/test/text/StringTest.kt +++ b/libraries/stdlib/test/text/StringTest.kt @@ -1856,4 +1856,17 @@ ${" "} assertTrue(null.contentEquals(null, ignoreCase = true)) assertTrue(null.contentEquals(null, ignoreCase = false)) } + + @Test + fun indexOfRespectsCharBoundary() { + withOneCharSequenceArg("\u003a\u3b3c\u003d") { input -> + assertEquals(-1, input.indexOf("\u3c00")) + assertEquals(-1, input.indexOf("\u3d3b")) + assertEquals(-1, input.indexOf("\u3c00\u3d3b")) + } + + // KT-56637 + assertEquals("買っ", "買っ".replace("掌", "X")) + assertEquals("買", "買".replace("掌", "X")) + } }