diff --git a/Sources/_StringProcessing/Engine/Processor.swift b/Sources/_StringProcessing/Engine/Processor.swift index 0bf19b829..0faf01332 100644 --- a/Sources/_StringProcessing/Engine/Processor.swift +++ b/Sources/_StringProcessing/Engine/Processor.swift @@ -767,7 +767,7 @@ extension String { let idx = unicodeScalars.index(after: pos) assert(idx <= end, "Input is a substring with a sub-scalar endIndex.") - if boundaryCheck && !isOnGraphemeClusterBoundary(idx) { + if boundaryCheck && idx != end && !isOnGraphemeClusterBoundary(idx) { return nil } @@ -788,7 +788,7 @@ extension String { guard cur <= end else { return nil } - if boundaryCheck && !isOnGraphemeClusterBoundary(cur) { + if boundaryCheck && cur != end && !isOnGraphemeClusterBoundary(cur) { return nil } diff --git a/Tests/RegexTests/MatchTests.swift b/Tests/RegexTests/MatchTests.swift index c8ad56073..d9508ddbf 100644 --- a/Tests/RegexTests/MatchTests.swift +++ b/Tests/RegexTests/MatchTests.swift @@ -3039,6 +3039,18 @@ extension RegexTests { XCTAssertNotNil("tesTs".wholeMatch(of: regex)) } + func testLiteralAtSubCharacterEnd() throws { + let cafe = "cafe\u{301}" + let sub = cafe[..(verbatim: "afe"))) + } + func testAutoPossessificationSkippedNodes() throws { firstMatchTest(#"(\w* {0})a"#, input: "a", match: "a") firstMatchTest(#"((\w* {0})){1}()a"#, input: "a", match: "a")