From 2f402eb3609ac8f14d77cf597a2804d9c97c885c Mon Sep 17 00:00:00 2001 From: Nate Cook Date: Mon, 26 Oct 2026 09:27:01 -0500 Subject: [PATCH] Match literal at end of sub-character substring Matching was failing for substrings that have a sub-character end index. This change fixes the boundary check for those cases, so that the end of the subject bounds is always a boundary. rdar://190999851 --- Sources/_StringProcessing/Engine/Processor.swift | 4 ++-- Tests/RegexTests/MatchTests.swift | 12 ++++++++++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/Sources/_StringProcessing/Engine/Processor.swift b/Sources/_StringProcessing/Engine/Processor.swift index 049ecaf23..cdd2bd3e5 100644 --- a/Sources/_StringProcessing/Engine/Processor.swift +++ b/Sources/_StringProcessing/Engine/Processor.swift @@ -799,7 +799,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 } @@ -820,7 +820,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 2d9a6b1c2..036265ad8 100644 --- a/Tests/RegexTests/MatchTests.swift +++ b/Tests/RegexTests/MatchTests.swift @@ -3058,4 +3058,16 @@ extension RegexTests { XCTAssertNotNil("testS".wholeMatch(of: regex)) XCTAssertNotNil("tesTs".wholeMatch(of: regex)) } + + func testLiteralAtSubCharacterEnd() throws { + let cafe = "cafe\u{301}" + let sub = cafe[..(verbatim: "afe"))) + } }